/**
 *
 * Copyright © 2012 Louis Chen.  All rights reserved.
 * Support Version Android >= 2.3 iOS >=4.0
 * This is for HSBC, and depend on jQuery & require
 * Version 0.1
 **/
// Nick added for browser support start
var runtimeVar = {
	configuration: {
		settings: {}
	}
};
// Nick added for browser support end
var iMobile = {};

function urlEncode(url) { 
	if (navigator.userAgent.match(/(iPad|iPhone|iPod)/g))  { 
		return escape(url); 
	} else { 
		return url;
	} 
} 


String.prototype.startsWith = function(str) {return (this.match("^"+str)==str)};
require.config({     //new added to config the alias
	paths : {
		"SaaS" : "../../../lib/js",
		"handoverToEntity" : "../../config/apis/handovertoentity",
		"handover" : "../../SAAS_handoverToEntity"
	}
}); 
iMobile.app = {
	getLocale : function(callbackjs){
		location.href = 'hsbc://function=GetLocale&callbackjs=' + callbackjs;
	},
	toggleMenu : function(){
		location.href = "hsbc://function=TogglePostLogonMenu";
	},	
	updateMenu : function(funcName,callbackFunc){
		location.href = "hsbc://function=UpdatePostLogonMenu&datajs=" + funcName+"&callbackjs="+callbackFunc;
	},
	updateBanner : function(imglink,onclickurl,callbackFunc){
		location.href = "hsbc://function=UpdateMenuBanner&imglink=" + imglink+"&onclickurl="+onclickurl+"&callbackjs="+callbackFunc;
	},
	toggleLanguage : function(switchLocale,callbackFunc){
		location.href = "hsbc://function=ToggleLanguage&locale="+switchLocale+"&callbackjs="+callbackFunc;
	},
	toggleServerLanguageEnd : function(result){
		location.href = "hsbc://function=ToggleServerLanguageEnd&result=" + result;
	},
	updateHtmlBanner : function(funcName,callbackFunc){
		location.href = "hsbc://function=UpdateMenuHtmlBanner&datajs=" + funcName+"&callbackjs="+callbackFunc;
	},
	openMainBrowserInApp : function(funcName,callbackFunc){
		location.href = "hsbc://function=OpenMainBrowserInApp&datajs=" + funcName+"&callbackjs="+callbackFunc;
	},
	switchEntityWithSso : function(datajs,callbackFunc){
		location.href = "hsbc://function=SwitchEntityWithSSO&datajs=" + datajs+"&callbackjs="+callbackFunc;
	},
	backToApp : function(locale, id){
		id = id || "home";
		location.href = "hsbc://function=BackToApp&id=" + id + "&lang=" + locale;
	},
	backToHome : function(){
		location.href = "hsbc://function=BackToHome";
	},
	proxy : function(datajs, callback, url, method){
		location.href = "hsbc://function=Proxy&datajs=" + datajs + "&callbackjs=" + callback + "&url=" + url + "&method=" + method;
	},
	proxyJSON : function(datajs, callback, url, method){
		location.href = "hsbc://function=ProxyJSON&datajs=" + datajs + "&callbackjs=" + callback + "&url=" + url + "&method=" + method;
	},
	pageTransition : function(path, fromRight2Left){
		fromRight2Left = fromRight2Left ? "LTR" : "RTL";
		// Nick added for browser support start
		if (runtimeVar.configuration.settings.isBrowser) {
			var href = location.href,
			    root = href.match(/(.*\/)web\//)[1];
			location.href = path.replace("file:///", root);
		} else
		// Nick added for browser support end
		location.href = 'hsbc://function=PageTransition&slide=' + fromRight2Left + '&url=' + path;
	},
	//setter
	setter : function(key,datajs,callbackjs){
		// Nick added for browser support start
		if (runtimeVar.configuration.settings.isBrowser) {
			console.log("hsbc://function=Setter&key=" + key + "&datajs=" + datajs + "&callbackjs=" + callbackjs);
			eval("runtimeVar." + key + "=" + datajs + "();")
			eval(callbackjs + "(" + datajs + "());");
		} else
		// Nick added for browser support start
		location.href = 'hsbc://function=Setter&key=' + key +'&datajs=' + datajs+ '&callbackjs=' + callbackjs;
	},
	getter : function(key, callbackjs){
		// Nick added for browser support start
		if (runtimeVar.configuration.settings.isBrowser) {
			console.log("hsbc://function=Getter&key=" + key + "&callbackjs=" + callbackjs);
			var data = runtimeVar[key] || "";
			eval(callbackjs + "(data);");
		} else
		// Nick added for browser support end
		location.href = 'hsbc://function=Getter&key=' + key + '&callbackjs=' + callbackjs;
	},
	getCookie : function(key, url, callbackjs){
		location.href = 'hsbc://function=GetCookies&url=' + url + '&key=' + key + '&callbackjs=' + callbackjs;
	},
	setCookie : function(key, url,datajs, callbackjs){
		location.href = 'hsbc://function=SetCookies&url=' + url + '&key=' + key +'&datajs='+datajs+'&callbackjs=' + callbackjs;
	},
	/**start Mobile1.5 Premier Pack 1**/
	openInApp : function(url,customerDataType){
		location.href = 'hsbc://function=OpenInApp&needCustomStyle=' + customerDataType + '&url=' + url;
	},
	/**end Mobile1.5 Premier Pack 1**/
	openInBrowser : function(url){
		location.href = 'hsbc://function=OpenInBrowser&url=' + url;
	},
	volatileGetter : function(key, callbackjs){
		location.href = 'hsbc://function=VolatileGetter&key=' + key + '&callbackjs='+ callbackjs;
	},
	volatileSetter : function(key, datajs , callbackjs){
		location.href = 'hsbc://function=VolatileSetter&key=' + key + '&datajs=' + datajs + '&callbackjs=' + callbackjs;
	},
	/* Added by Capgemini for proposition background [start] */
	volatileSetterForThemeId : function(datajs , callbackjs){
		location.href = 'hsbc://function=VolatileSetterForThemeId&datajs=' + datajs + '&callbackjs=' + callbackjs;
	},
	getMobileThemeId : function(callbackjs){
		location.href = 'hsbc://function=GetMobileThemeId&callbackjs='+callbackjs;
	},
	/* Added by Capgemini for proposition background [end] */
	switchWebModule : function(moduleId, callbackjs){
		location.href = 'hsbc://function=SwitchWebModule&moduleId=' + moduleId + '&callbackjs=' + callbackjs;
	},
	getDeviceInfo : function(callbackjs) {
		location.href = 'hsbc://function=GetDeviceInfo&callbackjs=' + callbackjs;
	},
	switchWebview : function(){
		location.href = 'hsbc://function=SwitchWebview';
	},
	postProcessEnd : function(){
		location.href = 'hsbc://function=PostProcessEnd';
	},
	/**
	 * functions of mobile soft token [start]
	**/
	getEncryptedGUID : function(callbackjs){
		location.href = 'hsbc://function=GetEncryptedGUID&callbackjs=' + callbackjs;
	},
	/* Added by Capgemini for SOTP implement [start] */
	isSyncronizeTimerequired : function(callbackjs){
		location.href = 'hsbc://function=isSyncronizeTimerequired&callbackjs=' + callbackjs;
	},
	/* Added by Capgemini for SOTP implement [end] */
	resynchronizeTime : function(timeStamp){
		location.href = 'hsbc://function=ResynchronizeTime&timestamp=' + timeStamp;
	},
	generateLogonOTP : function(datajs, callbackjs){
		location.href = 'hsbc://function=GenerateLogonOTP&datajs='+datajs+'&callbackjs='+callbackjs;
	},
	generateReauthOTP : function(datajs, callbackjs){
		location.href = 'hsbc://function=GenerateReauthOTP&datajs='+datajs+'&callbackjs='+callbackjs;
	},
	generateTxnOTP : function(datajs, callbackjs){
		location.href = 'hsbc://function=GenerateTxnOTP&datajs='+datajs+'&callbackjs='+callbackjs;
	},
	activateXFAD : function(datajs, callbackjs){
		location.href = 'hsbc://function=ActivateXFAD&datajs='+datajs+'&callbackjs='+callbackjs;
	},
	removeSoftToken : function(callbackjs){
		location.href = 'hsbc://function=RemoveSoftToken&callbackjs='+callbackjs;
	},
	generateRandomNumber : function(datajs, callbackjs){
		location.href = 'hsbc://function=GenerateRandomNumber&datajs='+datajs+'&callbackjs='+callbackjs;
	},
	getActivationArguments : function(datajs, callbackjs){
		location.href = 'hsbc://function=GetActivationArguments&datajs='+datajs+'&callbackjs='+callbackjs;
	},
	getMobileDOSI : function(callbackjs){
		location.href = 'hsbc://function=GetMobileDOSI&callbackjs='+callbackjs;
	},
	getPasscodeArguments : function(datajs, callbackjs){
		location.href = 'hsbc://function=GetPasscodeArguments&datajs='+datajs+'&callbackjs='+callbackjs;
	},
	isSupportSoftOTP : function(callbackjs){
		location.href = 'hsbc://function=IsSupportSoftOTP&callbackjs='+callbackjs;
	},
	reencryptSeed : function(datajs, callbackjs){
		location.href = 'hsbc://function=ReencryptSeed&datajs='+datajs+'&callbackjs='+callbackjs;
	},
	removeProgressBar : function(callbackjs){
		var cmd = '';
		if(callbackjs){
			cmd = '&callbackjs='+callbackjs;
		}
		location.href = 'hsbc://function=RemoveProgressBar' + cmd;
	},
	showMessageBox : function(datajs, callbackjs){
		location.href = 'hsbc://function=ShowMessageBox&datajs='+datajs+'&callbackjs='+callbackjs;
	},
	callDialPad : function(datajs, callbackjs){
		location.href = 'hsbc://function=CallDialPad&datajs='+datajs+'&callbackjs='+callbackjs;
	},
	setCurrentLogonState : function(datajs, callbackjs){
		location.href = 'hsbc://function=SetCurrentLogonState&datajs=' + datajs + '&callbackjs='+callbackjs;
	},
	setTokenType : function(datajs, callbackjs){
		location.href = 'hsbc://function=SetTokenType&datajs=' + datajs + '&callbackjs='+callbackjs;
	},
	getTokenType : function(callbackjs){
		location.href = 'hsbc://function=GetTokenType&callbackjs='+callbackjs;
	},
	/**
	 * functions of mobile soft token [end]
	**/
	updateBadgeNumber : function(num){
		location.href = 'hsbc://function=UpdateBadgeNumber&n='+num;
	},
	logonLoadingFinish : function(){
		location.href = 'hsbc://function=logonLoadingFinish';
	}
// IBTRM added start
	,
	registerBackToForeEvent: function (eventjs, callbackjs) {
		var url = ["hsbc://function=RegisterBackToForeEvent&eventjs=", eventjs];

		if(callbackjs){
			url.push("&callbackjs=", callbackjs);
		}

		location.href = url.join('');
	},
	unregisterBackToForeEvent: function (callbackjs) {
		var url = ['hsbc://function=UnregisterBackToForeEvent'];

		if(callbackjs){
			url.push("&callbackjs=", callbackjs);
		}

		location.href = url.join('');
	},
	showOverlay: function (url) {
		location.href = ['hsbc://function=ShowOverlay&url=', url].join('');
	},
	removeOverlay: function () {
		location.href = 'hsbc://function=RemoveOverlay';
	},
	switchSwipeGesture : function(switchValue,callbackjs){
		location.href = 'hsbc://function=SwitchSwipeGesture&switch='+switchValue+'&callbackjs='+callbackjs;
	},
	openInAppWithKeepAlive : function(url,customerDataType,settings){
		checkKeepAlive.registerCheckKeepAliveMethod("keepAliveCallBack",settings.isNeedKeepAlive,settings.checkKeepAliveSeconds,url,customerDataType);
	},
// IBTRM added end
	// Turn on mobile device camera for snapping.
	captureImage : function(datajs,callbackjs) {
        location.href = 'hsbc://function=CaptureImage&datajs=' + datajs + '&callbackjs=' + callbackjs;
    },
    // hook to check the device is mobile or tablet
    getDeviceType : function(callbackjs) {
        location.href = 'hsbc://function=GetDeviceType&callbackjs=' + callbackjs;
    },
    // hook to register a eventjs to receive the menu status
	registerMenuStatusEvent: function (eventjs, callbackjs) {
		var url = ["hsbc://function=RegisterMenuStatusEvent&eventjs=", eventjs];

		if(callbackjs){
			url.push("&callbackjs=", callbackjs);
		}

		location.href = url.join('');
	},
    // hook to unregister a eventjs to receive the menu status
	unregisterMenuStatusEvent: function (callbackjs) {
		var url = ['hsbc://function=UnregisterMenuStatusEvent'];

		if(callbackjs){
			url.push("&callbackjs=", callbackjs);
		}

		location.href = url.join('');
	},
	// hook to get application name
	getApplicationName: function (callbackjs) {
        location.href = 'hsbc://function=GetApplicationName&callbackjs=' + callbackjs;
	},
	// hook to show logoff dialog
	showLogoffDialog: function (callbackjs) {
		var url = ['hsbc://function=ShowLogoffDialog'];

		if(callbackjs){
			url.push("&callbackjs=", callbackjs);
		}

		location.href = url.join('');
	},
	/* added for Green Packet [start] */
	registerShakeListener: function(eventjs, callbackjs){
		location.href = 'hsbc://function=RegisterShakeListener&eventjs='+eventjs+'&callbackjs='+callbackjs;
	},
	registerMyLaiSeeListener: function(eventjs, callbackjs){
		location.href = 'hsbc://function=RegisterShakeListener&eventjs='+eventjs+'&callbackjs='+callbackjs;
	},
	unregisterShakeListener: function(callbackjs){
		location.href = 'hsbc://function=UnregisterShakeListener&callbackjs='+callbackjs;
	},
	registerLongPressListener: function(datajs, eventjs, callbackjs){
		// Nick added for browser support start
		if (runtimeVar.configuration.settings.isBrowser) {
			console.log("hsbc://function=RegisterLongPressListener&datajs=" + datajs + "&eventjs=" + eventjs + "&callbackjs=" + callbackjs);
			eval(callbackjs + "();");
		} else
		// Nick added for browser support end
		location.href = 'hsbc://function=RegisterLongPressListener&datajs='+datajs+'&eventjs='+eventjs+'&callbackjs='+callbackjs;
	},
	unregisterLongPressListener: function(callbackjs){
		// Nick added for browser support start
		if (runtimeVar.configuration.settings.isBrowser) {
			console.log("hsbc://function=UnregisterLongPressListener&callbackjs=" + callbackjs);
			eval(callbackjs + "();");
		} else
		// Nick added for browser support end
		location.href = 'hsbc://function=UnregisterLongPressListener&callbackjs='+callbackjs;
	},
	playSoundByType: function(datajs){
		location.href = 'hsbc://function=PlaySoundByType&type='+datajs;
	},
	/* added for Green Packet [end] */
	// Nick added for Green LaiSee start
	getEncryptedDeviceId: function(callbackjs) {
		// Nick added for browser support start
		if (runtimeVar.configuration.settings.isBrowser) {
			console.log("hsbc://function=GetEncryptedDeviceId&callbackjs=" + callbackjs);
			eval(callbackjs + "();");
		} else
		// Nick added for browser support end
		location.href = "hsbc://function=GetEncryptedDeviceId&callbackjs=" + callbackjs;
	},
	registerGestureListener: function(eventjs, callbackjs) {
		// Nick added for browser support start
		if (runtimeVar.configuration.settings.isBrowser) {
			console.log("hsbc://function=RegisterGestureListener&eventjs=" + eventjs +"&callbackjs=" + callbackjs);
			eval(callbackjs + "();");
		} else
		// Nick added for browser support end
		location.href = "hsbc://function=RegisterGestureListener&eventjs=" + eventjs +"&callbackjs=" + callbackjs;
	},
	unregisterGestureListener: function(callbackjs) {
		// Nick added for browser support start
		if (runtimeVar.configuration.settings.isBrowser) {
			console.log("hsbc://function=UnregisterGestureListener&callbackjs=" + callbackjs);
			eval(callbackjs + "();");
		} else
		// Nick added for browser support end
		location.href = "hsbc://function=UnregisterGestureListener&callbackjs=" + callbackjs;
	},
	validateSecureToken: function(value, callbackjs) {
		// Nick added for browser support start
		if (runtimeVar.configuration.settings.isBrowser) {
			console.log("hsbc://function=ValidateSecureToken&callbackjs=" + callbackjs + "&value=" + value);
			var isValidToken = value === "123456";
			eval(callbackjs + "(isValidToken);");
		} else
		// Nick added for browser support end
		location.href = "hsbc://function=ValidateSecureToken&callbackjs=" + callbackjs + "&value=" + value;
	}
	// Nick added for Green LaiSee end
};

iMobile.callBackStockHandler = function(param1,param2,param3,param4){
	var data = [param1,param2,param3,param4];
	var topic = Lang.topics['9c9eb9ae133cb5b9'];
	if(topic){
		var self = topic.delegate,adapt = topic.adapt, type = topic.type, name = topic.name;
		var hideLoadingFlag=topic.hideLoadingFlag;
		delete topic.adapt;
		delete topic.type;
		delete topic.name;
		delete topic.hideLoadingFlag;
		if(type == "NativeProxy"){
			self._analyse.apply(self,[data,adapt,function(result){	
				if(hideLoadingFlag==true)
				{
				 self.hideLoadingMask();
			  }
				self._messageHandler.apply(self,[name,topic.get().apply(self,[result]),result]);
			}]);			
		}
		else if(type == "JsonpProxy"){
			self._jsonpAnalyse.apply(self,[data,adapt,function(result){	
				if(hideLoadingFlag==true)
				{
				 self.hideLoadingMask();
			  }
				self._jsonpMessageHandler.apply(self,[name,topic.get().apply(self,[result]),result]);
			}]);			
		}
		else{
			topic.publishWith(self,[data]);
			if(hideLoadingFlag==true)
			{
			 self.hideLoadingMask();
		  }		
		}
	}
}

iMobile.callBackHandler = function(data){
	var topic = Lang.topics['9c9eb9ae133cb5b9'];
	if(topic){
		
		var self = topic.delegate,adapt = topic.adapt, type = topic.type, name = topic.name;
		var hideLoadingFlag=topic.hideLoadingFlag;
		delete topic.adapt;
		delete topic.type;
		delete topic.name;
		delete topic.hideLoadingFlag;
		if(type == "NativeProxy"){
			self._analyse.apply(self,[data,adapt,function(result){	
				if(hideLoadingFlag==true)
				{
				 self.hideLoadingMask();
			  }
				self._messageHandler.apply(self,[name,topic.get().apply(self,[result]),result]);
			}]);			
		}
		else if(type == "JsonpProxy"){
			self._jsonpAnalyse.apply(self,[data,adapt,function(result){	
				if(hideLoadingFlag==true)
				{
				 self.hideLoadingMask();
			  }
				self._jsonpMessageHandler.apply(self,[name,topic.get().apply(self,[result]),result]);
			}]);			
		}
		else{
			topic.publishWith(self,[data]);
			if(hideLoadingFlag==true)
			{
			 self.hideLoadingMask();
		  }		
		}
	}
}
/* added for Green Packet [start] */
iMobile.eventSetup = {
	eventListener : {},
	eventHandler : {},
	setEventListener : function(fn){
		var evtId = (new Date()).getTime().toString();
		iMobile.eventSetup.eventListener[evtId] = fn;
		iMobile.eventSetup.eventHandler[evtId] = function(data){// suitable for ONLY one argument
			var topic = Lang.topics['9c9eb9ae133cb5b9'];
			if(topic && $.isFunction(iMobile.eventSetup.eventListener[evtId])){
				var self = topic.delegate;
				iMobile.eventSetup.eventListener[evtId].call(self,data);
			}
		};
		return evtId;
	}
}
/* added for Green Packet [end] */
iMobile.dataJSHandler = function(){
	var topic = Lang.topics["da3ab016c46c426c"];
	if(topic){
		var self = topic.delegate, msg = topic.message;
		topic.message = {};
		return msg;
	}
	return '';
}
iMobile.messageJSHandler = function(){
	var topic = Lang.topics["da3ab016c46c426c"];
	if(topic){
		var self = topic.delegate, msg = topic.message;
		topic.message = {};
		return iCore.buildParams(msg);
	}
	return '';
}
iMobile.initError  = function(i18n){
	if(!validateUtil) return;
	validateUtil.Error_numeric = i18n.Error_numeric;
	validateUtil.Error_blank = i18n.Error_blank;
	validateUtil.Error_inValid = i18n.Error_inValid;
	validateUtil.Error_blankSpace = i18n.Error_blankSpace;
	validateUtil.Error_limitNum = i18n.Error_limitNum;
	validateUtil.Error_mostNum = i18n.Error_mostNum;
	validateUtil.Error_alphanumeric = i18n.Error_alphanumeric;
	validateUtil.Error_alphabetic = i18n.Error_alphabetic;
	validateUtil.Error_secPassword = i18n.Error_secPassword;
	validateUtil.Error_equal = i18n.Error_equal;
	validateUtil.Error_notEqual = i18n.Error_notEqual;
	validateUtil.Error_textArea = i18n.Error_textArea;
	validateUtil.Error_small = i18n.Error_small;
	validateUtil.Error_great = i18n.Error_great;
	validateUtil.Error_early = i18n.Error_early;
	validateUtil.Error_earlyToday = i18n.Error_earlyToday;
	validateUtil.Error_inValidSeparator = i18n.Error_inValidSeparator;
	validateUtil.Error_inValidNumber = i18n.Error_inValidNumber;
	validateUtil.Error_positive = i18n.Error_positive;
	validateUtil.Error_phone = i18n.Error_phone;
	validateUtil.errHead = i18n.errHead;
	validateUtil.errFoot = i18n.errFoot;
	validateUtil.Error_adapt_field_type= i18n.Error_adapt_field_type;
	validateUtil.Error_adapt_not_instance= i18n.Error_adapt_not_instance;
	validateUtil.Error_adapt_invalid_property= i18n.Error_adapt_invalid_property;
	validateUtil.Error_adapt_required= i18n.Error_adapt_required;
	validateUtil.Error_adapt_pattern= i18n.Error_adapt_pattern;
	validateUtil.Error_adapt_maxlength= i18n.Error_adapt_maxlength;
	validateUtil.Error_adapt_minlength= i18n.Error_adapt_minlength;
	validateUtil.Error_adapt_minimum= i18n.Error_adapt_field_type;
	validateUtil.Error_adapt_maximum= i18n.Error_adapt_field_type;
	validateUtil.Error_adapt_enumeration= i18n.Error_adapt_enumeration;
	validateUtil.Error_adapt_digits= i18n.Error_adapt_digits;
	validateUtil.Error_adapt_object_required= i18n.Error_adapt_object_required;
	validateUtil.Error_adapt_additional= i18n.Error_adapt_additional;
	validateUtil.Error_adapt_presence= i18n.Error_adapt_presence;
};
/**
 * Multiple request message JS handler.
 */
iMobile.multipleRequestMessageJSHandler = function(taskId){
	var self = this;
	try {
		if (taskId && multipleRequestDelegate) {
			var task = multipleRequestDelegate.getProcessedTaskById(taskId);
			var options = task.options;
			if (options.data) {
				var params = $.isFunction(options.data) ? options.data.call(self) : options.data, topic = Lang.topics["da3ab016c46c426c"];
				topic.message = $.extend(topic.message||{},{
					"locale" : self.locale
				},params||{});
				var msg = topic.message;
				topic.message = {};
				return iCore.buildParams(msg);
			}
		}
		return '';
	} finally {
		if (task && task.deferred) {
			task.deferred.resolve();
		}
	}
};
/**
 * Multiple request callback JS handler.
 */	
iMobile.multipleCallbackHandler = function(taskId, data) {
	if (taskId && multipleRequestDelegate) {
		var options = multipleRequestDelegate.getProcessedTaskById(taskId).options;
		var adapt = 'adaptor/' + options.name + '_resp';
		if (options.adaptorPath != undefined) {
			adapt = options.adaptorPath + adapt;
		}
		var topic = Lang.topics['9c9eb9ae133cb5b9'];
		var self = topic.delegate;
		self._analyse.apply(self, [data, adapt,
		function (result) {
			// remove the task from buffer.processedTasks
			var index = multipleRequestDelegate.getProcessedTaskIndexById(taskId);
			if (index == -1) {
				console.error("multipleCallbackHandler cannot find the task from processedTask.");
			} else {
				multipleRequestDelegate.removeProcessedTaskAt(index);
			}
			if (multipleRequestDelegate.getProcessedTasks().length == 0) {
				self.hideLoadingMask();
			}
			self._messageHandler.apply(self, [options.name, options.callback.apply(window, [result]), result]);
		}])
	}
};

(function() {
  /**
* From: http://code.this.com/mobile/articles/fast_buttons.html
* Also see: http://stackoverflow.com/questions/6300136/trying-to-implement-googles-fast-button
*/
   
  /** For IE8 and earlier compatibility: https://developer.mozilla.org/en/DOM/element.addEventListener */
  function addListener(el, type, listener, useCapture) {
    if (el.addEventListener) {
      el.addEventListener(type, listener, useCapture);
      return {
        destroy: function() { el.removeEventListener(type, listener, useCapture); }
      };
    } else {
      // see: http://stackoverflow.com/questions/5198845/javascript-this-losing-context-in-ie
      var handler = function(e) { listener.handleEvent(window.event, listener); }
      el.attachEvent('on' + type, handler);
      
      return {
        destroy: function() { el.detachEvent('on' + type, handler); }
      };
    }
  }
  
  var isTouch = "ontouchstart" in window;

  /* Construct the FastButton with a reference to the element and click handler. */
  this.FastButton = function(element, handler, useCapture) {
    // collect functions to call to cleanup events
    this.events = [];
    this.touchEvents = [];
    this.element = element;
    this.handler = handler;
    this.useCapture = useCapture;
    if (isTouch)
      this.events.push(addListener(element, 'touchstart', this, this.useCapture));
    this.events.push(addListener(element, 'click', this, this.useCapture));
  };
  
  /* Remove event handling when no longer needed for this button */
  this.FastButton.prototype.destroy = function() {
    for (var i = this.events.length - 1; i >= 0; i -= 1)
      this.events[i].destroy();
    this.events = this.touchEvents = this.element = this.handler = this.fastButton = null;
  };
  
  /* acts as an event dispatcher */
  this.FastButton.prototype.handleEvent = function(event) {
    switch (event.type) {
      case 'touchstart': this.onTouchStart(event); break;
      case 'touchmove': this.onTouchMove(event); break;
      case 'touchend': this.onClick(event); break;
      case 'click': this.onClick(event); break;
    }
  };
  
  /* Save a reference to the touchstart coordinate and start listening to touchmove and
touchend events. Calling stopPropagation guarantees that other behaviors don’t get a
chance to handle the same click event. This is executed at the beginning of touch. */
  this.FastButton.prototype.onTouchStart = function(event) {
    event.stopPropagation ? event.stopPropagation() : (event.cancelBubble=true);
    this.touchEvents.push(addListener(this.element, 'touchend', this, this.useCapture));
    this.touchEvents.push(addListener(document.body, 'touchmove', this, this.useCapture));
    this.startX = event.touches[0].clientX;
    this.startY = event.touches[0].clientY;
  };
  
  /* When /if touchmove event is invoked, check if the user has dragged past the threshold of 10px. */
  this.FastButton.prototype.onTouchMove = function(event) {
    if (Math.abs(event.touches[0].clientX - this.startX) > 10 || Math.abs(event.touches[0].clientY - this.startY) > 10) {
      this.reset(); //if he did, then cancel the touch event
    }
  };
  
  /* Invoke the actual click handler and prevent ghost clicks if this was a touchend event. */
  this.FastButton.prototype.onClick = function(event) {
    event.stopPropagation ? event.stopPropagation() : (event.cancelBubble=true);
    this.reset();
    // Use .call to call the method so that we have the correct "this": https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Function/call
    var result = this.handler.call(this.element, event);
    if (event.type == 'touchend')
      clickbuster.preventGhostClick(this.startX, this.startY);
    return result;
  };
  
  this.FastButton.prototype.reset = function() {
    for (i = this.touchEvents.length - 1; i >= 0; i -= 1)
      this.touchEvents[i].destroy();
    this.touchEvents = [];
  };
  
  this.clickbuster = function() {}
  
  /* Call preventGhostClick to bust all click events that happen within 25px of
the provided x, y coordinates in the next 2.5s. */
  this.clickbuster.preventGhostClick = function(x, y) {
    clickbuster.coordinates.push(x, y);
    window.setTimeout(clickbuster.pop, 2500);
  };
  
  this.clickbuster.pop = function() {
    clickbuster.coordinates.splice(0, 2);
  };
  
  /* If we catch a click event inside the given radius and time threshold then we call
stopPropagation and preventDefault. Calling preventDefault will stop links
from being activated. */
  this.clickbuster.onClick = function(event) {
    for (var i = 0; i < clickbuster.coordinates.length; i += 2) {
      var x = clickbuster.coordinates[i];
      var y = clickbuster.coordinates[i + 1];
      if (Math.abs(event.clientX - x) < 25 && Math.abs(event.clientY - y) < 25) {
        event.stopPropagation ? event.stopPropagation() : (event.cancelBubble=true);
        event.preventDefault ? event.preventDefault() : (event.returnValue=false);
      }
    }
  };
    
  if (isTouch) {
    // Don't need to use our custom addListener function since we only bust clicks on touch devices
    document.addEventListener('click', clickbuster.onClick, true);
    clickbuster.coordinates = [];
  }
})(this);
//fast click
(function($) {
  $.fn.fastClick = function(handler) {
    return $(this).each(function() {
      new FastButton($(this)[0], handler);
    });
  };
}(jQuery));
/**
 * JSON validate
 * Lastupdatedby Louis Y P Chen 20/Mar/2012 HKT
 */
(function(){
	//setup the primitive class for the types
	var privateT = {
			'string' : String,
			'boolean': Boolean,
			'number' : Number,
			'object' : Object,
			'array' : Array,
			'date': Date
	};
	//
	var adaptRegister = iMobile.adaptRegister = function(/*JSON Object*/obj, /*Object*/adapt, /*Object*/options){
		options = options || {};
		var _changing = options.changing || false;
		//internal get type function
		function getType(adapt){
			return adapt.type || (privateT[adapt.name] === adapt && adapt.name.toLowerCase()); 
		}
		//To store the error(s)
		var errors = [];
		// validate a value against a property definition
		function checkProp(value, adapt, path, i){
			var l;
			path += path ? typeof i == 'number' ? '[' + i + ']' : typeof i == 'undefined' ? '' : '.' + i : i;
			function addError(message){
				errors[errors.length] = {property : path, message : message};
			}
			if((typeof adapt != 'object' || adapt instanceof Array) && (path || typeof adapt != 'function') && !(adapt && getType(adapt))){
				if(typeof adapt == 'function'){
					if(!(value instanceof adapt)){
						//addError("is not an instance of the class/constructor " + adapt.name);
						addError(validateUtil['Error_adapt_not_instance'].replace(/~~1/,adapt.name));
					}
				}else if(adapt){
					//addError("Invalid adapt/property definition " + adapt);
					addError(validateUtil['Error_adapt_invalid_property'].replace(/~~1/,adapt));
				}
				return null;
			}
			if(adapt['extends']){ // if it extends another schema, it must pass that schema as well
				checkProp(value,adapt['extends'],path,i);
			}
			// validate a value against a type definition
			function checkType(type,value){
				if(type){
					if(typeof type == 'string' && type != 'any' &&(type == 'null' ? value !== null : typeof value != type) &&
							!(value instanceof Array && type == 'array') && !(value instanceof Date && type == 'date') &&
							!(type == 'integer' && value % 1 === 0)){

						//return [{property:path,message:(typeof value) + " value found, but a " + type + " is required"}];
						return [{property:path,message: validateUtil['Error_adapt_field_type'].replace(/~~1/,(typeof value)).replace(/~~2/,type)}];
					}
					if(type instanceof Array){
						var unionErrors = [];
						for(var j = 0; j < type.length; j++){ // a union type
							if(!(unionErrors=checkType(type[j],value)).length){
								break;
							}
						}
						if(unionErrors.length){
							return unionErrors;
						}
					}else if(typeof type == 'object'){
						var priorErrors = errors;
						errors = [];
						checkProp(value,type,path);
						var theseErrors = errors;
						errors = priorErrors;
						//clear the tmp
						priorErrors = null;
						return theseErrors;
					}
				}
				return [];
			}
			if(value === undefined){
				if(adapt.required){
					//addError("is missing and it is required");
					addError(validateUtil['Error_adapt_required']);
				}
			}else{
				errors = errors.concat(checkType(getType(adapt),value));
				if(value != null){
					if(value instanceof Array){
						if(adapt.items){
							var itemsIsArray = adapt.items instanceof Array;
							var propDef = adapt.items;
							for (i = 0, l = value.length; i < l; i += 1) {
								if(itemsIsArray){
									propDef = adapt.items[i];
								}
								errors.concat(checkProp(value[i],propDef,path,i));
							}
						}
					}else if(adapt.properties || adapt.additionalProperties){
						errors.concat(checkObj(value, adapt.properties, path, adapt.additionalProperties));
					}
					if(adapt.pattern && typeof value == 'string' && !value.match(adapt.pattern)){
						//addError("does not match the regex pattern " + adapt.pattern);
						addError(validateUtil['Error_adapt_pattern'].replace(/~~1/,adapt.pattern));
					}
					if(adapt.maxLength && typeof value == 'string' && value.length > adapt.maxLength){
						//addError("may only be " + adapt.maxLength + " characters long");
						addError(validateUtil['Error_adapt_maxlength'].replace(/~~1/,adapt.maxLength));
					}
					if(adapt.minLength && typeof value == 'string' && value.length < adapt.minLength){
						//addError("must be at least " + adapt.minLength + " characters long");
						addError(validateUtil['Error_adapt_minlength'].replace(/~~1/,adapt.minLength));
					}
					if(typeof adapt.minimum !== undefined && typeof value == typeof adapt.minimum &&
							adapt.minimum > value){
						//addError("must have a minimum value of " + adapt.minimum);
						addError(validateUtil['Error_adapt_minimum'].replace(/~~1/,adapt.minimum));
					}
					if(typeof adapt.maximum !== undefined && typeof value == typeof adapt.maximum &&
							adapt.maximum < value){
						//addError("must have a maximum value of " + adapt.maximum);
						addError(validateUtil['Error_adapt_maximum'].replace(/~~1/,adapt.maximum));
					}
					if(adapt['enum']){
						var enumer = adapt['enum'];
						l = enumer.length;
						var found;
						for(var j = 0; j < l; j++){
							if(enumer[j]===value){
								found=1;
								break;
							}
						}
						if(!found){
							//addError("does not have a value in the enumeration " + enumer.join(", "));
							addError(validateUtil['Error_adapt_enumeration'].replace(/~~1/,enumer.join(", ")));
						}
					}
					if(typeof adapt.maxDecimal == 'number' &&
							(value.toString().match(new RegExp("\\.[0-9]{" + (schema.maxDecimal + 1) + ",}")))){
						//addError("may only have " + adapt.maxDecimal + " digits of decimal places");
						addError(validateUtil['Error_adapt_digits'].replace(/~~1/,adapt.maxDecimal));
					}
				}
			}
			return null;
		}
		//validate an object against an adapt
		function checkObj(instance,objTypeDef,path,additionalProp){
			if(typeof objTypeDef =='object'){
				if(typeof instance != 'object' || instance instanceof Array){
					//errors.push({property:path,message:"an object is required"});
					errors.push({property:path,message:validateUtil['Error_adapt_object_required']});
				}
				for(var i in objTypeDef){
					if(objTypeDef.hasOwnProperty(i)){
						var value = instance[i];
						// skip _not_ specified properties
						if (value === undefined){
							if(objTypeDef[i].required){
								//errors.push({property: i,message:"is missing and it is required"});
								errors.push({property: (path + "." + i),message:validateUtil['Error_adapt_required']});
							}
							continue;
						}
						//
						var propDef = objTypeDef[i];
						// set default
						if(value === undefined && propDef["default"]){
							value = instance[i] = propDef["default"];
						}
						//replace() to avoid XSS attack
						if(value && typeof value === "string"){
							value = value.replace(/<\/?\s*script\s*[^>]*>/gi, "");
							instance[i] = value;
						}
						checkProp(value,propDef,path,i);
					}
				}
			}
			for(i in instance){
				if(instance.hasOwnProperty(i) && !(i.charAt(0) == '_' && i.charAt(1) == '_') && objTypeDef && !objTypeDef[i] && additionalProp===false){
					//errors.push({property:path,message:(typeof value) + "The property " + i +
					//	" is not defined in the adapt and the adapt does not allow additional properties"});
					errors.push({property:path,message:validateUtil['Error_adapt_additional'].replace(/~~1/,(typeof value)).replace(/~~2/,i)});
				}
				if(!objTypeDef.hasOwnProperty(i)){
					//filter the object
					delete instance[i];
				}
				var requires = objTypeDef && objTypeDef[i] && objTypeDef[i].requires;
				if(requires && !(requires in instance)){
					//errors.push({property:path,message:"the presence of the property " + i + " requires that " + requires + " also be present"});
					errors.push({property:path,message:validateUtil['Error_adapt_presence'].replace(/~~1/,i).replace(/~~2/,requires)});
				}
				value = instance[i];
				if(additionalProp && (!(objTypeDef && typeof objTypeDef == 'object') || !(i in objTypeDef))){
					checkProp(value,additionalProp,path,i);
				}
				if(!_changing && value && value.$schema){
					errors = errors.concat(checkProp(value,value.$schema,path,i));
				}
			}
			return errors;
		}
		if(adapt){
			checkProp(obj,adapt,'', _changing || '');
		}
		if(!_changing && obj && obj.$schema){
			checkProp(obj,obj.$schema,'','');
		}
		return {valid:!errors.length,errors:errors};
	};	
})();

//
iCore.superclass = iBase;
iCore.synthesizedProperties = ["messageForProxy","keyframe"];
function iCore(){
	var self = this;
	self.callSuper();
	self.locale = 'en';
	this.delegate = null;
	//self.index = -1;
	self.iViewControllers = {};
	self._history = [];
	self.keyframe = "slideleft";
	self.currentViewController = null;
	self.devType = ""; //webtrend enhancement for android tablet
	self.platform="";
	var isIos=(/iphone|ipad/gi).test(navigator.appVersion);
  if(Lang.isAndroid){
  	self.platform="A";
  }else if(isIos){
  	self.platform="I";
  }
	// Nick added for GreenLaiSee start
	self.encryptedDeviceId = "";
	// Nick added for GreenLaiSee end
	require([self.configuration.settings],function(settings){
		self.configuration.settings = settings;
		// Nick added for browser support start
		if (settings.isBrowser) {
			runtimeVar.configuration.settings = settings;
		}
		// Nick added for browser support end
		//self.configuration.auth = auth;
		//console.log(auth);
		//dim
		Lang.topics["a6d38804ceb86f18"].subscribe(iFunction.dimOrNotBaseOnRequireFields);
		/**start MobileUI1.5P2 hot-hot M0001**/
		//self.getDomain();
		/**end MobileUI1.5P2 hot-hot M0001**/

		/**webtrend enhancement for android tablet - start**/
		if(Lang.isAndroid && !self.configuration.settings.dummy){
			self.getDeviceType(function(type){				
				self.devType = type;
				self.getDomain();
			});
		}else{
			self.getDomain();
		}
		/**webtrend enhancement for android tablet - end**/
		
	});
}
/**start MobileUI1.5P2 hot-hot M0001**/
iCore.prototype.getDomain= function()
{
	var self=this;
	if(self.configuration.settings.isMultipleDomain && self.isLogon!=true){
		 self.getter(self.configuration.settings.serverDomain,self.getDomainCallBack);
	}else{
		 self.runGetLocale();
	}
}

iCore.prototype.runGetLocale= function()
{
	var self =this;
	if(self.configuration.settings.isBrowser){
			self.getLocale(self.locale);
	}else{
		// Nick added for GreenLaiSee start
		// get encrypted device id from app
		self.getEncryptedDeviceId(function(deviceId) {
			self.encryptedDeviceId = deviceId;
			self.hookRequire("getLocale", ["iMobile.callBackHandler"], self.getLocale);
		});
		// Nick added for GreenLaiSee end
	}
}
/**end MobileUI1.5P2 hot-hot M0001**/
iCore.prototype.hookRequire = function(name,args,callback){
	if(!$.isArray(args)) return;
	var self = this, topic = Lang.topics['9c9eb9ae133cb5b9'];
	if(topic && callback && $.isFunction(callback)){
		topic.empty();
		topic.subscribe(callback);
	}
	iMobile.app[name].apply(self,args);
}

iCore.prototype.reauthCheckSubmitData = function(){
	 return  {
	  "ver":"1.1",
	  "json":""
	};
}
iCore.prototype.timeoutLogoffData = function(){
	 return  {
	  "ver":"1.1",
	  "json":""
	};
}
iCore.prototype.timeoutLogoffCallback = function(){
	  var self = this;
	  return {
        "success": function (jsonData) {
           self.backToHome();
        },
        "error": function (jsonData) {
        	self.backToHome();
        }
    }	
}
iCore.prototype.reauthCheckCallBack = function(){	
	  var self = this;
	  return {
        "success": function (jsonData) {
            var data = jsonData.data;
            if (data.body.hasOwnProperty('rccDigits')&&data.body.rccDigits!=null) {
                //Cam30 reAuth
                self.fillCam30(data.body.rccDigits);
                $("#reauth_secondPassword").removeClass("hidden");
                $("#idv_OtpCredential").addClass("hidden");
                $("#reauthCam30_confirm").removeClass("hidden").addClass("disabled");
                $("#reauthCam30_confirm").attr("aria-disabled","true");
                $("#reauthCam40_confirm").addClass("hidden");
                $("#reauthCam30H1").removeClass("hidden");
                $("#reauthCam40_btn_help").addClass("hidden");
                $("#reauthCam40H1").addClass("hidden");
                $("#passwordsInfoCAM40").addClass("hidden");
                $("#reauth_passwordsInfoCAM30").removeClass("hidden");
            } else {
                //Cam40 reAuth
                $("#reauth_passwordsInfoCAM30").addClass("hidden");
                $("#passwordsInfoCAM40").removeClass("hidden");
                $("#reauth_secondPassword").addClass("hidden");
                $("#idv_OtpCredential").val("").removeClass("hidden");
                $("#reauthCam30_confirm").addClass("hidden");
                /* implement for SOTP [start] */
                if(self._usingSOTP === true && !$('#idv_OtpCredential').attr('state')){// it is using SOTP and first time to reauth
                	$('#idv_OtpCredential').replaceWith('<input id="idv_OtpCredential" maxlength="'+self.configuration.settings.SOTP.PCD_MAX_LEN+'" type="password" placeholder="'+self.configuration.auth.pcdDesc+'" state="done"/>');
                	$("#passwordsInfoCAM40 > h4").html(self.configuration.auth.sotpInfo);
                	$('#reauthCam40H1').html(self.configuration.auth.securityCodeDesc);
                }
                /* implement for SOTP [end] */
                $("#reauthCam40_confirm").removeClass("hidden").addClass("disabled");
                $("#reauthCam30_confirm").attr("aria-disabled","true");
                $("#reauthCam30H1").addClass("hidden");
                $("#reauthCam40H1").removeClass("hidden");
                $("#reauthCam40_btn_help").removeClass("hidden");
            }
            self.goTo("reAuth","fade");
        },
        "error": function (jsonData) {}
    }
}

iCore.prototype.fillCam30 = function(rccDigits){	
	  var self = this;
	  var auth=self.configuration.auth;
	  var secPwdString = " " + auth.cam30PwdInfo1 + " ";
    var result = $("#reauth_secondPassword").children().is("input");
    if (result) {
        // empty the input data
        $("#reauth_secondPassword").empty();
    }
    for (var i = 0, j = 1; i < 8; i++, j++) {
        $("#reauth_secondPassword").append("<input id='secPwdPosition" + j + "' type='password' size='1' class='ui-input grayPwd hidden' maxlength='1' readonly='readonly' /><div id='greyBox"+j+"' class='ui-grey-box'></div>");
        if (i == 5) {
            $("#reauth_secondPassword").append("<h1>...</h1>");
        }
    }
    var dualPwdPositonArray = rccDigits.split(",");
    var secondPwdInput1, secondPwdInput2, secondPwdInput3;
    for (var i = 0, j = 1; i < dualPwdPositonArray.length; i++, j++) {
        var temp = dualPwdPositonArray[i];
        var showStr = "";
        $("#secPwdPosition" + temp).removeClass("grayPwd").removeClass("hidden");
        $("#secPwdPosition" + temp).removeAttr("readonly");
        $("#secPwdPosition" + temp).addClass("dualPwd");
        $("#greyBox"+temp).addClass("hidden");	
        switch (temp) {
        case "1":
            secPwdString += auth.first;
            showStr = auth.placeH1;
            break;
        case "2":
            secPwdString += auth.second;
            showStr = auth.placeH2;
            break;
        case "3":
            secPwdString += auth.third;
            showStr = auth.placeH3;
            break;
        case "4":
            secPwdString += auth.fourth;
            showStr = auth.placeH4;
            break;
        case "5":
            secPwdString += auth.fifth;
            showStr = auth.placeH5;
            break;
        case "6":
            secPwdString += auth.sixth;
            showStr = auth.placeH6;
            break;
        case "7":
            secPwdString += auth.secondLast;
            showStr = auth.placeH7;
            break;
        case "8":
            secPwdString += auth.last;
            showStr = auth.placeH8;
            break;
        default:
            secPwdString += auth.other;
        }
        switch (j) {
        case 1:
            secondPwdInput1 = "secPwdPosition" + temp;
            secPwdString += ", ";
            break;
        case 2:
            secondPwdInput2 = "secPwdPosition" + temp;
            secPwdString += " and ";
            break;
        case 3:
            secondPwdInput3 = "secPwdPosition" + temp;
            secPwdString += " ";
            break;
        default:
            secPwdString += " ";
        }
        $("#secPwdPosition" + temp).attr("placeholder", showStr);
    }
    secPwdString += "" + auth.cam30PwdInfo2;
    $("#reauth_passwordsInfoCAM30").html("<h4>" + secPwdString + "</h4>");
    $("#" + secondPwdInput1).val("");
    $("#" + secondPwdInput2).val("");
    $("#" + secondPwdInput3).val("");
    self._cam30FieldArr = {};
    self._cam30FieldArr[secondPwdInput1] = {
        isEmpty: true
    };
    self._cam30FieldArr[secondPwdInput2] = {
        isEmpty: true
    };
    self._cam30FieldArr[secondPwdInput3] = {
        isEmpty: true
    };
}
/**
 * Hook API 
 */
iCore.prototype.request = function(options){
	var options = options||{}, self = this;
	/**start MobileUI1.5P2 hot-hot M0001**/
	//show loading
	if(options.showLoadingFlag!=false)
	{
	 this.showLoadingMask(options.loadingMsg||'');
  }
  /**end MobileUI1.5P2 hot-hot M0001**/
	var topic = Lang.topics['9c9eb9ae133cb5b9'];
	topic.type = "NativeProxy";
	topic.name = options.name;
	topic.hideLoadingFlag=true;
	if(options.hideLoadingFlag!=undefined)
	{
	   topic.hideLoadingFlag=options.hideLoadingFlag;
	}
	iData.add("lastReq",options);
	var adapt='adaptor/' + options.name + '_resp';
	
	if(options.adaptorPath!=undefined)
	    adapt=options.adaptorPath+adapt;
	topic.adapt = adapt;
	if(this.configuration.settings.dummy){
		require(['../../dummy/'+ self.locale + '/' + options.name + '.resp'], function(data){
			self._analyse.apply(self,[data,adapt, function(result){
				if(options.callback && $.isFunction(options.callback)){
					var handler = options.callback.call(self,result);
					self._messageHandler.apply(self,[options.name,handler,result]);
				}
			}]);		
			self.hideLoadingMask();		
		});
	}else{
		if(options.data){
			var params = $.isFunction(options.data) ? options.data.call(self) : options.data, topic = Lang.topics["da3ab016c46c426c"];
			topic.message = $.extend(topic.message||{},{
				"locale" : self.locale,
				// Nick added for GreenLaiSee start
				"deviceId": self.encryptedDeviceId
				// Nick added for GreenLaiSee end
			},params||{});
		}
		var url="";
		if(options.url!=undefined && options.url!='')
		{
			url=options.url;
		}
		else
		{
		 url=self.apis[options.name].url;
		 if(self.apis[options.name].url!=undefined&&self.apis[options.name].url[self.locale]!=undefined)
		 {
		 	 url=self.apis[options.name].url[self.locale];
		 }
		}
		/**start MobileUI1.5P2 hot-hot M0001**/
		var currentDomain=self.currentDomain;
		/**end MobileUI1.5P2 hot-hot M0001**/
		if(!url.startsWith("http") && !url.startsWith("https"))
	  {
	  	var pwsHost=self.configuration.settings.pwsHost;
	  	var isHavePwsHost=self.configuration.settings.isHavePwsHost;
	  	
	  	var hnaHost=self.configuration.settings.hnaHost;
	  	var isHaveHnaHost=self.configuration.settings.isHaveHnaHost;
	  	
	  	if(self.isPws==true && isHavePwsHost==true)
	  	{
	  		url=pwsHost+url;
	  	}else if(self.isHna==true && isHaveHnaHost==true){
	  		url=hnaHost+url;
	  		}
	  	/**start MobileUI1.5P2 hot-hot M0001**/
	  	else 
	  	{
		  	if(currentDomain!=undefined && currentDomain!=''&&self.configuration.settings.isMultipleDomain==true)
		  	{
		  		url=self.configuration.settings.protocolString+currentDomain+url;
		    }
		  	else
		  	{
				  url=self.configuration.settings.host+url;
				}
		  }
			/**end MobileUI1.5P2 hot-hot M0001**/
		}
		self.hookRequire("proxy",['iMobile.messageJSHandler','iMobile.callBackHandler',url,options.method],options.callback);
	}
}
iCore.prototype.jsonpRequest = function(options){
	var options = options||{}, self = this;
	/**start MobileUI1.5P2 hot-hot M0001**/
	//show loading
	if(options.showLoadingFlag!=false)
	{
	 this.showLoadingMask(options.loadingMsg||'');
  }
  /**end MobileUI1.5P2 hot-hot M0001**/
	var topic = Lang.topics['9c9eb9ae133cb5b9'];
	topic.type = "JsonpProxy";
	topic.name = options.name;
	topic.hideLoadingFlag=true;
	if(options.hideLoadingFlag!=undefined)
	{
	   topic.hideLoadingFlag=options.hideLoadingFlag;
	}
	iData.add("lastReq",options);
	var adapt='adaptor/' + options.name + '_resp';
	
	if(options.adaptorPath!=undefined)
	    adapt=options.adaptorPath+adapt;
	topic.adapt = adapt;
	if(this.configuration.settings.dummy){
		require(['../../dummy/'+ self.locale + '/' + options.name + '.resp'], function(data){
			self._jsonpAnalyse.apply(self,[data,adapt, function(result){
				if(options.callback && $.isFunction(options.callback)){
					var handler = options.callback.call(self,result);
					self._jsonpMessageHandler.apply(self,[options.name,handler,result]);
				}
			}]);		
			self.hideLoadingMask();		
		});
	}else{
		if(options.data){
			var params = $.isFunction(options.data) ? options.data.call(self) : options.data, topic = Lang.topics["da3ab016c46c426c"];
			topic.message = $.extend(topic.message||{},{
				"callback":"jsonpCallback"
			},params||{});
		}
		var url="";
		if(options.url!=undefined && options.url!='')
		{
			url=options.url;
		}
		else
		{
		 url=self.apis[options.name].url;
		 if(self.apis[options.name].url!=undefined&&self.apis[options.name].url[self.locale]!=undefined)
		 {
		 	 url=self.apis[options.name].url[self.locale];
		 }
		}
	  /**start MobileUI1.5P2 hot-hot M0001**/
		var currentDomain=self.currentDomain;
		/**end MobileUI1.5P2 hot-hot M0001**/
		if(!url.startsWith("http") && !url.startsWith("https"))
	  {
	  	var pwsHost=self.configuration.settings.pwsHost;
	  	var isHavePwsHost=self.configuration.settings.isHavePwsHost;
		
		var hnaHost=self.configuration.settings.hnaHost;
	  	var isHaveHnaHost=self.configuration.settings.isHaveHnaHost;
		
	  	if(self.isPws==true && isHavePwsHost==true)
	  	{
	  		url=pwsHost+url;
	  	}else if(self.isHna==true && isHaveHnaHost==true){
	  		url=hnaHost+url;
	  		}
	  	/**start MobileUI1.5P2 hot-hot M0001**/
	  	else 
	  	{
		  	if(currentDomain!=undefined && currentDomain!=''&&self.configuration.settings.isMultipleDomain==true)
		  	{
		  		url=self.configuration.settings.protocolString+currentDomain+url;
		    }
		  	else
		  	{
				  url=self.configuration.settings.host+url;
				}
		  }
			/**end MobileUI1.5P2 hot-hot M0001**/
		}
		self.hookRequire("proxy",['iMobile.messageJSHandler','iMobile.callBackHandler',url,options.method],options.callback);
	}
}
/**
 * Multiple request Hook API. 
 */
iCore.prototype.multipleRequest = function(options) {
	if(this.configuration.settings.dummy){
		var options = options||{}, self = this;
		var adapt='adaptor/' + options.name + '_resp';	
		if(options.adaptorPath!=undefined) adapt=options.adaptorPath+adapt;
		require(['../../dummy/' + options.name + '.resp'], function(data){
			self._analyse.apply(self,[data,adapt, function(result){
				if(options.callback && $.isFunction(options.callback)){
					var handler = options.callback.call(self,result);
					self._messageHandler.apply(self,[options.name,handler,result]);
				}
			}]);
			self.hideLoadingMask();
		});
		return;
	}
	$.fn.multipleRequestProxy.multipleRequest(options,this);
}
//getter
iCore.prototype.getter = function(name,callback){
	this.hookRequire('getter',[name,"iMobile.callBackHandler"],callback);
}
//setter
iCore.prototype.setter = function(name,data,callback){
	this.messageForProxy = data;
	this.hookRequire('setter',[name,'iMobile.dataJSHandler','iMobile.callBackHandler'],callback);
}
//volatileGetter
iCore.prototype.volatileGetter = function(name,callback){
	this.hookRequire('volatileGetter',[name,"iMobile.callBackHandler"],callback);
}
//volatileSetter
iCore.prototype.volatileSetter = function(name,data,callback){
	this.messageForProxy = data;
	this.hookRequire('volatileSetter',[name,'iMobile.dataJSHandler','iMobile.callBackHandler'],callback);
}
/* Added by Capgemini for proposition background [start] */
iCore.prototype.volatileSetterForThemeId = function(data,callback){
	this.messageForProxy = data;
	this.hookRequire('volatileSetterForThemeId',['iMobile.dataJSHandler','iMobile.callBackHandler'],callback);
}
iCore.prototype.getMobileThemeId = function(callbackjs){
	this.hookRequire('getMobileThemeId',['iMobile.callBackHandler'],callbackjs);
}
/* Added by Capgemini for proposition background [end] */
//switchWebModule 
iCore.prototype.switchWebModule = function(moduleId,callback){
	this.hookRequire('switchWebModule',[moduleId,'iMobile.callBackHandler'],callback);
}
//setCookie
iCore.prototype.setCookie = function(name,domain,data,callback){
	this.messageForProxy = data;
	this.hookRequire('setCookie',[name,domain,'iMobile.dataJSHandler','iMobile.callBackHandler'],callback);
}
//getCookie
iCore.prototype.getCookie = function(name,domain,callback){
	this.hookRequire('getCookie',[name,domain,'iMobile.callBackHandler'],callback);
}
//open in app
/**start Mobile1.5 Premier Pack 1**/
iCore.prototype.openInApp = function(url){
	var self = this;
	url=iFunction.setQueryForUiIfNeeded(self.getUrl(url));
	this.hookRequire('openInApp',[url,self.preCusLogon]);
}
/**end Mobile1.5 Premier Pack 1**/
//open in browser
iCore.prototype.openInBrowser = function(url){
	this.hookRequire('openInApp',[url]);
}
//toggleMenu
iCore.prototype.toggleMenu = function(){
	this.hookRequire('toggleMenu',[]);
}
//update native menu
iCore.prototype.updateMenu = function(data,callback){
	this.messageForProxy = data;
	this.hookRequire('updateMenu',['iMobile.dataJSHandler','iMobile.callBackHandler'],callback);
}
//update html banner
iCore.prototype.updateHtmlBanner = function(data,callback){
	this.messageForProxy = data;
	this.hookRequire('updateHtmlBanner',['iMobile.dataJSHandler','iMobile.callBackHandler'],callback);
}
iCore.prototype.openMainBrowserInApp = function(data,callback){
	this.messageForProxy = data;
	this.hookRequire('openMainBrowserInApp',['iMobile.dataJSHandler','iMobile.callBackHandler'],callback);
}

//switchEntityWithSso
iCore.prototype.switchEntityWithSso  = function(data,callback){
	this.messageForProxy = data;
	this.hookRequire('switchEntityWithSso',['iMobile.dataJSHandler','iMobile.callBackHandler'],callback);
}
//toggle language
iCore.prototype.toggleLanguage = function(switchLocale,callback){
	this.hookRequire('toggleLanguage',[switchLocale,'iMobile.callBackHandler'],callback);
}
//toggle language end
iCore.prototype.toggleServerLanguageEnd = function(result){
	this.hookRequire('toggleServerLanguageEnd',[result]);
}
//update native bannar
iCore.prototype.updateBanner = function(imgUrl,srcUrl,callback){
	this.hookRequire('updateBanner',[imgUrl,srcUrl,'iMobile.callBackHandler'],callback);
}
iCore.prototype.getUrl = function(url){
	var self = this;
	var currentDomain=self.currentDomain;
	if(!url.startsWith("http") && !url.startsWith("https"))
	{
  	var pwsHost=self.configuration.settings.pwsHost;
  	var isHavePwsHost=self.configuration.settings.isHavePwsHost;
  	
	var hnaHost=self.configuration.settings.hnaHost;
	var isHaveHnaHost=self.configuration.settings.isHaveHnaHost;
	
  	if(self.isPws==true && isHavePwsHost==true)
  	{
  		url=pwsHost+url;
  	}else if(self.isHna==true && isHaveHnaHost==true){
	  		url=hnaHost+url;
	  		}
  
  	else 
  	{
	  	if(currentDomain!=undefined && currentDomain!=''&&self.configuration.settings.isMultipleDomain==true)
	  	{
	  		url=self.configuration.settings.protocolString+currentDomain+url;
	    }
	  	else
	  	{
			  url=self.configuration.settings.host+url;
			}
	  }
	}
	return url;
}

//get public site host
iCore.prototype.getPwsHost = function(){
	var self = this;
	return self.configuration.settings.pwsHost;
}

iCore.prototype.getHnaHost = function(){
	var self = this;
	return self.configuration.settings.hnaHost;
}

//update date picker
iCore.prototype.updateDatePicker = function(datePickerId,optKey,optValue){
	if(optKey == "validatedDates"){
		$("#"+datePickerId).datepicker("option","beforeShowDay",function (date) {  
			if(optValue == null || optValue.length <= 0){
				return [true,'']
			}
			
			for (i = 0; i < optValue.length; i++) {  
        		if (date.getFullYear() == optValue[i].getFullYear() && date.getMonth() == optValue[i].getMonth()  
        		&& date.getDate() == optValue[i].getDate()) {  
        			var tmpString = date.getFullYear() + "_day";
        			return [true, tmpString];  
        		}  
			}

        	return [false,''];  
		});
		
	}else if(optKey == "defaultDate"){
		if(optValue == null || optValue == ""){
			$("#"+datePickerId).datepicker("setDate" , new Date());
		}
		$.datepicker.setDatepickerStatus(datePickerId,optValue);
	}else if(optKey == "setDate"){
		$("#"+datePickerId).datepicker("setDate" , optValue);
	}else{
		$("#"+datePickerId).datepicker("option",optKey,optValue);
	}
}
/**
 * functions of mobile soft token [start]
**/
iCore.prototype.getEncryptedGUID = function(callbackjs){
	//Hsbc.mobile.app.getEncryptedGUID(callbackjs);
	this.hookRequire('getEncryptedGUID',['iMobile.callBackHandler'],callbackjs);
}
/* Added by Capgemini for SOTP implement [start] */
iCore.prototype.isSyncronizeTimerequired = function(callbackjs){
	//Hsbc.mobile.app.isSyncronizeTimerequired(callbackjs);
	this.hookRequire('isSyncronizeTimerequired',['iMobile.callBackHandler'],callbackjs);
}
/* Added by Capgemini for SOTP implement [end] */
iCore.prototype.resynchronizeTime = function(timeStamp){
	//Hsbc.mobile.app.resynchronizeTime(timeStamp);
	this.messageForProxy = timeStamp;
	this.hookRequire('resynchronizeTime',[timeStamp]);
}
iCore.prototype.generateLogonOTP = function(datajs, callbackjs){
	//Hsbc.mobile.app.generateLogonOTP(datajs, callbackjs);
	this.messageForProxy = datajs;
	this.hookRequire('generateLogonOTP',['iMobile.dataJSHandler','iMobile.callBackHandler'],callbackjs);
}
iCore.prototype.generateReauthOTP = function(datajs, callbackjs){
	//Hsbc.mobile.app.generateReauthOTP(datajs, callbackjs);
	this.messageForProxy = datajs;
	this.hookRequire('generateReauthOTP',['iMobile.dataJSHandler','iMobile.callBackHandler'],callbackjs);
}
iCore.prototype.generateTxnOTP = function(datajs, callbackjs){
	//Hsbc.mobile.app.generateTxnOTP(datajs, callbackjs);
	this.messageForProxy = datajs;
	this.hookRequire('generateTxnOTP',['iMobile.dataJSHandler','iMobile.callBackHandler'],callbackjs);
}
iCore.prototype.activateXFAD = function(datajs, callbackjs){
	//Hsbc.mobile.app.activateXFAD(datajs, callbackjs);
	this.messageForProxy = datajs;
	this.hookRequire('activateXFAD',['iMobile.dataJSHandler','iMobile.callBackHandler'],callbackjs);
}
iCore.prototype.removeSoftToken = function(callbackjs){
	//Hsbc.mobile.app.removeSoftToken(callbackjs);
	this.hookRequire('removeSoftToken',['iMobile.callBackHandler'],callbackjs);
}
iCore.prototype.generateRandomNumber = function(datajs, callbackjs){
	//Hsbc.mobile.app.generateRandomNumber(datajs, callbackjs);
	this.messageForProxy = datajs;
	this.hookRequire('generateRandomNumber',['iMobile.dataJSHandler','iMobile.callBackHandler'],callbackjs);
}
iCore.prototype.getActivationArguments = function(datajs, callbackjs){
	//Hsbc.mobile.app.getActivationArguments(datajs, callbackjs);
	this.messageForProxy = datajs;
	this.hookRequire('getActivationArguments',['iMobile.dataJSHandler','iMobile.callBackHandler'],callbackjs);
}
iCore.prototype.getMobileDOSI = function(callbackjs){
	//Hsbc.mobile.app.getMobileDOSI(callbackjs);
	this.hookRequire('getMobileDOSI',['iMobile.callBackHandler'],callbackjs);
}
iCore.prototype.getPasscodeArguments = function(datajs, callbackjs){
	//Hsbc.mobile.app.getPasscodeArguments(datajs, callbackjs);
	this.messageForProxy = datajs;
	this.hookRequire('getPasscodeArguments',['iMobile.dataJSHandler','iMobile.callBackHandler'],callbackjs);
}
iCore.prototype.isSupportSoftOTP = function(callbackjs){
	//Hsbc.mobile.app.isSupportSoftOTP(callbackjs);
	this.hookRequire('isSupportSoftOTP',['iMobile.callBackHandler'],callbackjs);
}
iCore.prototype.reencryptSeed = function(datajs, callbackjs){
	//Hsbc.mobile.app.reencryptSeed(datajs, callbackjs);
	this.messageForProxy = datajs;
	this.hookRequire('reencryptSeed',['iMobile.dataJSHandler','iMobile.callBackHandler'],callbackjs);
}
iCore.prototype.removeProgressBar = function(callbackjs){
	//Hsbc.mobile.app.removeProgressBar(callbackjs);
	if(callbackjs){
		this.hookRequire('removeProgressBar',['iMobile.callBackHandler'],callbackjs);
	}else{
		this.hookRequire('removeProgressBar',[]);
	}
}
iCore.prototype.showMessageBox = function(datajs, callbackjs){
	//Hsbc.mobile.app.showMessageBox(datajs, callbackjs);
	this.messageForProxy = datajs;
	this.hookRequire('showMessageBox',['iMobile.dataJSHandler','iMobile.callBackHandler'],callbackjs);
}
iCore.prototype.callDialPad = function(datajs, callbackjs){
	//Hsbc.mobile.app.callDialPad(datajs, callbackjs);
	this.messageForProxy = datajs;
	this.hookRequire('callDialPad',['iMobile.dataJSHandler','iMobile.callBackHandler'],callbackjs);
}
iCore.prototype.setCurrentLogonState = function(datajs, callbackjs){
	this.messageForProxy = datajs;
	this.hookRequire('setCurrentLogonState',['iMobile.dataJSHandler','iMobile.callBackHandler'],callbackjs);
}
iCore.prototype.setTokenType = function(datajs, callbackjs){
	this.messageForProxy = datajs;
	this.hookRequire('setTokenType',['iMobile.dataJSHandler','iMobile.callBackHandler'],callbackjs);
}
iCore.prototype.getTokenType = function(callbackjs){
	this.hookRequire('getTokenType',['iMobile.callBackHandler'],callbackjs);
}
/**
 * functions of mobile soft token [end]
**/
//date picker
iCore.prototype.initDatePicker = function(opts){
	if(!$.datepicker) return;
	var self = this;
	//require([self.configuration.dps + "_" + self.locale], function(dps){
		//self.configuration.dpsConfig=dps;
		var dps = self.configuration.dpsConfig;
		var dates = [];
		$.datepicker.regional[self.locale] = {
				monthNames : dps.monthNames,
				closeText	:	dps.monthNames,
				prevText	: dps.prevText,
				nextText	: dps.nextText,
				v_prevText	: dps.v_prevText,
				v_nextText	: dps.v_nextText,
				currentText	: dps.currentText,
				monthNames	: dps.monthNames,
				monthNamesShort	: dps.monthNamesShort,
				dayNames	: dps.dayNames,
				dayNamesShort	: dps.dayNamesShort,
				dayNamesMin	: dps.dayNamesMin,
				weekHeader	: dps.weekHeader,
				firstDay	: dps.firstDay,
				isRTL	: dps.isRTL,
				showMonthAfterYear	: dps.showMonthAfterYear,
				yearSuffix	: dps.yearSuffix
		};
		$.datepicker.setDefaults($.datepicker.regional[self.locale]);
		if(opts.validatedDates != null && opts.validatedDates.length > 0) {
			opts.minDate = null;
			opts.maxDate = null;
		}
		$("#"+opts.datePickerId).datepicker(
			{
				showButtonPanel: opts.showButtonPanel||false,
				showOtherMonths:opts.showOtherMonths||false,
				minDate: opts.minDate?opts.minDate:"",
				maxDate: opts.maxDate?opts.maxDate:"",
				today : opts.today?opts.today:dps.today,
				todayDate : opts.todayDate?opts.todayDate:"",
				choosedDateFont : opts.choosedDateFont?opts.choosedDateFont:"",
				datepickerStatus : dps.datepickerStatus,
				dateNoSelected: dps.datepickerStatus,
				dateSelected : dps.dateSelected,
				showDateFormat: opts.showDateFormat != null && opts.showDateFormat != "" ? opts.showDateFormat : dps.showDateFormat,
				beforeShowDay: opts.beforeShowDay? opts.beforeShowDay : function (date) {  
					if(opts.validatedDates == null || opts.validatedDates.length <= 0){
						return [true,'']
					}
					
					for (i = 0; i < opts.validatedDates.length; i++) {  
		        		if (date.getFullYear() == opts.validatedDates[i].getFullYear() && date.getMonth() == opts.validatedDates[i].getMonth()  
		        		&& date.getDate() == opts.validatedDates[i].getDate()) {  
		        			var tmpString = date.getFullYear() + "_day";
		        			return [true, tmpString];  
		        		}  
					}

		        	return [false,''];  
		        },
				defaultDate:opts.defaultDate?opts.defaultDate:"",
				onSelect: function(date){
				
					//Default Date
					dates[2] = date;
					var date = date.split("/");
					var year = date[2];
					var month = date[1];
					var day = date[0];
					
					var dateFormatSetting = {
							'dayNamesShort': dps.dayNamesShort,
							'dayNames': dps.dayNamesMin,
							'monthNamesShort': dps.monthNamesShort,
							'monthNames': dps.monthNames
					};
					var showDateFormat = opts.showDateFormat != null && opts.showDateFormat != "" ? opts.showDateFormat : dps.showDateFormat;
					var submitDateFormat = opts.submitDateFormat != null && opts.submitDateFormat != "" ? opts.submitDateFormat : dps.submitDateFormat;
					//showDate
					dates[0] = $.datepicker.formatDate(showDateFormat,new Date(month + "/" + day + "/" + year),dateFormatSetting);
					//submitDate
					dates[1] = $.datepicker.formatDate(submitDateFormat,new Date(month + "/" + day + "/" + year),dateFormatSetting);
					if(opts.onSelect){
						opts.onSelect.apply(window,dates);
					}
			}
		});
		if(opts.defaultDate != null){
			$.datepicker.setDatepickerStatus(opts.datePickerId,opts.defaultDate);
		}
		
	//});
}

iCore.prototype.setKeyframe = function(name){
	this._keyframe = iMobile.keyframes[name] || iMobile.keyframes['slideleft'];
}
iCore.prototype.getKeyframe = function(){
	return this._keyframe;
}
iCore.prototype.updateBadgeNumber = function(num){
	//Hsbc.mobile.app.updateBadgeNumber(num);
	this.hookRequire('updateBadgeNumber',[num]);
}
/**
 * Hook API end
 */
iCore.buildParams = function(instance){
	var params = $.param(instance);
	if(params && params.indexOf('=')==0){
		params = params.substr(1);
	}
	return params;	
}
/**
 *  direction 
 *      - slideleft, slideright, slideup, slidedown
 */
//current we only support below transitions
iMobile.keyframes = {
	"slideleft" : {
		"wasBackItemTransition" : Lang.keyframes.iViewControllerTransitionInFromLeft,
		"becomesBackItemTransition" : Lang.keyframes.iViewControllerTransitionOutToLeft,
		"wasTopItemTransition" : Lang.keyframes.iViewControllerTransitionOutToRight,
		"becomesTopItemTransition" : Lang.keyframes.iViewControllerTransitionInFromRight
	},
	"slideright" : {
		"wasBackItemTransition" : Lang.keyframes.iViewControllerTransitionInFromRight,
		"becomesBackItemTransition" : Lang.keyframes.iViewControllerTransitionOutToRight,
		"wasTopItemTransition" : Lang.keyframes.iViewControllerTransitionOutToLeft,
		"becomesTopItemTransition" : Lang.keyframes.iViewControllerTransitionInFromLeft		
	},
	"slideup" : {
		"wasBackItemTransition" : Lang.keyframes.iViewControllerTransitionInFromUp,
		"becomesBackItemTransition" : Lang.keyframes.iViewControllerTransitionOutToUp,
		"wasTopItemTransition" : Lang.keyframes.iViewControllerTransitionOutToDown,
		"becomesTopItemTransition" : Lang.keyframes.iViewControllerTransitionInFromDown		
	},
	"slidedown" : {
		"wasBackItemTransition" : Lang.keyframes.iViewControllerTransitionInFromDown,
		"becomesBackItemTransition" : Lang.keyframes.iViewControllerTransitionOutToDown,
		"wasTopItemTransition" : Lang.keyframes.iViewControllerTransitionOutToUp,
		"becomesTopItemTransition" : Lang.keyframes.iViewControllerTransitionInFromUp		
	},
	"flip" : {
		"wasBackItemTransition" : Lang.keyframes.iViewTransitionFlipRightIn,
		"becomesBackItemTransition" : Lang.keyframes.iViewTransitionFlipLeftOut,
		"wasTopItemTransition" : Lang.keyframes.iViewTransitionFlipRightOut,
		"becomesTopItemTransition" : Lang.keyframes.iViewTransitionFlipLeftIn
	},
	"fade" : {
		"wasBackItemTransition" : Lang.keyframes.iViewTransitionDissolveIn,
		"becomesBackItemTransition" : Lang.keyframes.iViewTransitionDissolveOut,
		"wasTopItemTransition" : Lang.keyframes.iViewTransitionDissolveOut,
		"becomesTopItemTransition" : Lang.keyframes.iViewTransitionDissolveIn		
	}
}

iCore.prototype.setTransition = function(controller){
	if(!controller) return null;
	controller.wasBackItemTransition = this.keyframe.wasBackItemTransition;
	controller.becomesBackItemTransition = this.keyframe.becomesBackItemTransition;
	controller.wasTopItemTransition = this.keyframe.wasTopItemTransition;
	controller.becomesTopItemTransition = this.keyframe.becomesTopItemTransition;
	return controller;
}

function _killKeyboard(){
		try {
			if(document.activeElement && document.activeElement.nodeName.toLowerCase() != 'body') {
				$(document.activeElement).blur();
			} else {
				$( "input:focus, textarea:focus, select:focus" ).blur();
			}
		} catch(e) {}
}

iCore.prototype.goTo = function(target, direction){
	var self = this;
	if(direction === true){
		self.hookRequire('pageTransition',[target,self.configuration.rdirect]);
	}else{
		self.fromDcsUri=$(self.currentViewController.view.layer).find("div[role=headbar]").attr('dcsuri');
		this.keyframe = direction || 'slideleft';	
		if(direction!=undefined && direction!="slideleft" && direction!="slideright" )
		{
		  $("#"+target).attr("style","");
	  }
	  self._scrollTop=$(window).scrollTop();
	  if(Lang.isOS5 || Lang['android4-']){
			 self._scrollTop=$(self.currentViewController.view.layer).find('div[role=content]').scrollTop();
		}
		var controller = this.setTransition(self.iViewControllers[target]);
	  
		//
		self.controller.topViewController.wasBackItemTransition = this.keyframe.wasBackItemTransition;
		self.controller.topViewController.becomesBackItemTransition = this.keyframe.becomesBackItemTransition;
		self.controller.topViewController.wasTopItemTransition = this.keyframe.wasTopItemTransition;
		self.controller.topViewController.becomesTopItemTransition = this.keyframe.becomesTopItemTransition;	
		this.currentViewController = controller;
		
		_killKeyboard();
		self.controller.pushViewControllerAnimated(controller);
		$("#"+target).find('div[role=content]').scrollTop(0);
		window.scrollTo(0,0);
		this._history.unshift(target);
		
		controller = null;
		
		self.pageStatusIsChanged($("#" + target));
	}
}
iCore.prototype.backToApp = function(){
	this.hookRequire('backToApp',[this.locale,"home"]);
}
iCore.prototype.backToHome = function(){
	this.hookRequire('backToHome',[]);
}
iCore.prototype.goBack = function(target, inPages){
	inPages = !!inPages;
	var self = this;
	if(inPages){
		self.hookRequire('pageTransition',[target,self.configuration.rdirect ? false : true]);
	}else{
		if(this._history.length == 1){
			this.backToApp();
			return false;
		}
		var isFromView=false;
    var currentPage=$(self.currentViewController.view.layer);
		if(currentPage.hasClass('view')){
		   isFromView=true;
		}
		self.fromDcsUri=$(self.currentViewController.view.layer).find("div[role=headbar]").attr('dcsuri');
		target = self.iViewControllers[target] || self.controller._viewControllers[self.controller._viewControllers.length - 2];
		this.currentViewController = target;
		_killKeyboard();
		self.controller.popToViewControllerAnimated(target);
		//enhance the stack
		if(this._history.length > 1){
			if(this._history[1] === target){
				this._history.shift();
			}else{
				var index = -1;
				for(var i = 0; i< this._history.length; i++){
					if(this._history[i] === target){
						index = i;
						break;
					}
				}
				if(index > 1){
					index = index - 1;
					while(index >= 0){
						this.hist.splice(0,1);
						index--;
					}
				}
			}
		}	
		if(!isFromView)
		{
			if(Lang.isOS5 || Lang['android4-']){
			  $(self.currentViewController.view.layer).find('div[role=content]').scrollTop(0);
			}
		}
		else
		{
			if(!Lang.isOS5 && !Lang['android4-']){
				$(window).scrollTop(self._scrollTop);
			}else{
				//if(Lang['android4-']){
				$(self.currentViewController.view.layer).find('div[role=content]').scrollTop(self._scrollTop);
			}
		}

		self.pageStatusIsChanged(self.currentViewController.view.layer);
	}
}

iCore.prototype.resetRequireField = function(){
	$('input[require=true],textarea[require=true],select[require=true],a>di[require=true]').each(function(index,obj){ 
	    this.valued = false;
	});  
}

var Hsbc = {
		mobile : {
			fn : {
				androidBack : function(){
					var self = iFunction.delegate;
					if(self._multipleLogonError!=undefined && self._multipleLogonError==true)
					{
						self.backToHome();
						return;
					}
					var currentPage=$(self.currentViewController.view.layer);
					if(currentPage.find("a.ui-back")[0] && (currentPage.find("a.ui-back").css('display')!='none' || currentPage.find("a.ui-back:eq(0)").hasClass('ui-back-hard'))){						
						//special handle for pre stock quote
						if(currentPage.attr('id') == "prelogon_stock_Quotes"){
							self.switchWebview();
						}else{
							currentPage.find("a.ui-back").click();						
						} 
						
					}else if(currentPage.find("a.ui-android-back")[0] && (currentPage.find("a.ui-android-back").css('display')!='none' || currentPage.find("a.ui-android-back:eq(0)").hasClass('ui-android-back-hard'))){						
						currentPage.find("a.ui-android-back").click();
					}else if(currentPage.find("a.ui-android-ok")[0] && (currentPage.find("a.ui-android-ok").css('display')!='none' || currentPage.find("a.ui-android-ok:eq(0)").hasClass('ui-android-ok-hard'))){						
						currentPage.find("a.ui-android-ok").click();
					}
					else
					{						
						var currentId=currentPage.attr('id');
						if(currentPage.hasClass('prelogon') || currentPage.hasClass('disableAndroidBack'))
						{
							self.backToHome();
							return ;
						}
						self.showLogoffDialog();
					}
				}
			}
		}
};

iCore.prototype.showLoadingMask = function(msg){
	var loader = $('body > div.ui-loaderWrapper');
	if(!this._loadingMask && loader.length == 0){
		this._loadingMask = $('<div id="loadingMask" class="ui-loader ui-loaderWrapper"><div class="loading defa ui-corner-all"><div class="loader"></div><div class="loadtext"></div></div></div>');
		$('body').append(this._loadingMask);
	}else{
		this._loadingMask = loader;
	}
	if(msg && Lang.isString(msg)){
		this._loadingMask.find('div.loadtext').html(msg);
	}else{
		this._loadingMask.find('div.loadtext').html("");
	}
	loader = null;
	var h = 0;
	if(Lang.isOS5 || Lang['android4-']){
		h = window.innerHeight;
	}else{
		h = $(document).height();
	}
	this._loadingMask.css({
		height : h
	}).removeClass('hidden').show();

	this.pageStatusIsChanged(false);
}

iCore.prototype.logonLoadingFinish = function(){
	this.hookRequire('logonLoadingFinish',[]);
}

iCore.prototype.hideLoadingMask = function(){
	(this._loadingMask ? this._loadingMask.hide() : $('body > div.ui-loader').hide());

	this.pageStatusIsChanged(this.currentViewController.view.layer);
}
iCore.prototype.setMessageForProxy = function(data){
	Lang.topics["da3ab016c46c426c"].message = data||"";
}
iCore.prototype.getMessageForProxy = function(){
	return Lang.topics["da3ab016c46c426c"].message||"";
}
iCore.prototype.getDeviceInfo = function(callback) {
	this.hookRequire('getDeviceInfo',['iMobile.callBackStockHandler'],callback);
}
iCore.prototype.switchWebview = function(){
	var self = this;
	this.hookRequire('switchWebview',[]);
}
iCore.prototype.postProcessEnd = function(){
	var self = this;
	this.hookRequire('postProcessEnd',[]);
}
iCore.prototype.showTokenTypeHelpPage = function(helpPageObj,str){
	var self = this;
	
	self.volatileGetter('user_tokenType',function(val){
		var tempUrl = "";
    	switch(val){
			case "DP270":
			tempUrl = helpPageObj["DP270"];			    
				break;
			case "PIN_DP270":
				tempUrl = helpPageObj["Pin_DP270"];			    
				break;
			case "DP050":
				tempUrl = helpPageObj["DP050"];	    
				break;
			case "GO3":
				tempUrl = helpPageObj["GO3"];
				break;
			case "DP302":
				tempUrl = helpPageObj["DP302"];
				break;					
			default:
				tempUrl = helpPageObj["default"];							  
		}
		tempUrl = self.getUrl(tempUrl);
		
		if(str == undefined){
			self.openInApp(tempUrl);			
		}else{
			self.openInApp(tempUrl+str);
		}		
	});
}
/* Added for Core SOTP - WebTrends delay calling [start] */
iCore.prototype.webTrendsDelayCall = function(pageId){
	var self = this;
	var wtURI = $('#'+pageId).find("div[role=headbar]").attr('dcsuri');
	runTrackWebtrends(self.configuration.settings.wtSettings,self.locale,wtURI);
}
/* Added for Core SOTP - WebTrends delay calling [end] */
iCore.prototype.pageStatusIsChanged = function(target){
	var self = this;

	// use timeout to prevent repeated call
	if(this.pageStatusIsChangedTimeout) {
		window.clearTimeout(this.pageStatusIsChangedTimeout);
	}
	
	if(typeof PostLogonMenu !== 'undefined') {
		this.pageStatusIsChangedTimeout = window.setTimeout(function(){
			if(target === true || (target !== false && !(self.configuration.settings.isDisableMenuInVerifyAndConfirmationPage && $('.ui-header', target).hasClass('withoutBg')))) {
				if ($.isFunction(PostLogonMenu.enableMenu)){
					PostLogonMenu.enableMenu();
				}
			}
			else {
				if ($.isFunction(PostLogonMenu.disableMenu)){
					PostLogonMenu.disableMenu();
				}
			}
		}, 50);
	}
}

/* Menu Gesture */
iCore.prototype.switchSwipeGesture = function(switchValue,callback){
	this.hookRequire('switchSwipeGesture',[switchValue,'iMobile.callBackHandler'],callback);
}
/* Keep Alive */
iCore.prototype.openInAppWithKeepAlive = function(url){
	var self = this;
	url=iFunction.setQueryForUiIfNeeded(self.getUrl(url));
	this.hookRequire('openInAppWithKeepAlive',[url,self.preCusLogon,self.configuration.settings]);
}

// Turn on mobile device camera for snapping.
iCore.prototype.captureImage = function (datajs, callbackjs){
	var self=this;
	// Mark Harding - include option for dummy response
	if(self.configuration.settings.dummy){
		console.log('load dummy data');
		require(['../../dummy/captureImages.resp'], function(data){
			if (callbackjs && $.isFunction(callbackjs)){
				callbackjs($.toJSON(data));
			}
		});
		return true;
	}
	this.messageForProxy = datajs;
	this.hookRequire('captureImage', ['iMobile.dataJSHandler', 'iMobile.callBackHandler'], callbackjs);
}
// function to check the device is tablet or mobile
iCore.prototype.getDeviceType = function(callback) {
	this.hookRequire('getDeviceType',['iMobile.callBackHandler'],callback);
}

// function to register a eventjs to receive the menu status
iCore.prototype.registerMenuStatusEvent = function (callback) {
	var args=["iFunction.menuStatusEventJS"];
	if(callback){
		args.push('iMobile.callBackHandler');
		this.hookRequire('registerMenuStatusEvent',args,callback);
	} else {
		this.hookRequire('registerMenuStatusEvent',args);
	}
}

// function to unregister a eventjs to receive the menu status
iCore.prototype.unregisterMenuStatusEvent = function (callback) {
	var args=[];
	if(callback){
		args.push('iMobile.callBackHandler');
		this.hookRequire('unregisterMenuStatusEvent',args,callback);
	} else {
		this.hookRequire('unregisterMenuStatusEvent',args);
	}
}

//function to get application name
iCore.prototype.getApplicationName = function (callback) {
	this.hookRequire('getApplicationName',['iMobile.callBackHandler'],callback);
}

//function to show logoff dialog
iCore.prototype.showLogoffDialog = function (callback) {
	var args=[];
	if(callback){
		args.push('iMobile.callBackHandler');
		this.hookRequire('showLogoffDialog',args,callback);
	} else {
		this.hookRequire('showLogoffDialog',args);
	}
}

/* added for Green Packet [start] */
iCore.prototype.registerShakeListener = function(eventjs, callbackjs){
	var id = iMobile.eventSetup.setEventListener(eventjs);
	console.log('iMobile.eventSetup.eventHandler["'+id+'"]()');
	this.hookRequire('registerShakeListener', ['iMobile.eventSetup.eventHandler["'+id+'"]', 'iMobile.callBackHandler'], callbackjs);
}
iCore.prototype.registerMyLaiSeeListener = function(eventjs, callbackjs){
	var id = iMobile.eventSetup.setEventListener(eventjs);
	console.log('iMobile.eventSetup.eventHandler["'+id+'"]()');
	this.hookRequire('registerMyLaiSeeListener', ['iMobile.eventSetup.eventHandler["'+id+'"]', 'iMobile.callBackHandler'], callbackjs);
}
iCore.prototype.unregisterShakeListener = function(callbackjs){
	this.hookRequire('unregisterShakeListener',['iMobile.callBackHandler'],callbackjs);
}
iCore.prototype.registerLongPressListener = function(datajs, eventjs, callbackjs){
	var id = iMobile.eventSetup.setEventListener(eventjs);
	console.log('iMobile.eventSetup.eventHandler["'+id+'"]()');
	this.messageForProxy = datajs;
	this.hookRequire('registerLongPressListener', ['iMobile.dataJSHandler', 'iMobile.eventSetup.eventHandler[\''+id+'\']', 'iMobile.callBackHandler'], callbackjs);
}
iCore.prototype.unregisterLongPressListener = function(callbackjs){
	this.hookRequire('unregisterLongPressListener',['iMobile.callBackHandler'],callbackjs);
}
iCore.prototype.playSoundByType = function(type){
	this.hookRequire('playSoundByType',[type]);
}
/* added for Green Packet [end] */

// Nick added for Green LaiSee start
iCore.prototype.getEncryptedDeviceId = function(callbackjs) {
	this.hookRequire("getEncryptedDeviceId", ["iMobile.callBackHandler"], callbackjs);
};

iCore.prototype.registerGestureListener = function(eventjs, callbackjs) {
	var id = iMobile.eventSetup.setEventListener(eventjs);
	this.hookRequire("registerGestureListener", ["iMobile.eventSetup.eventHandler[\"" + id + "\"]", "iMobile.callBackHandler"], callbackjs);
};

iCore.prototype.unregisterGestureListener = function(callbackjs) {
	this.hookRequire("unregisterGestureListener", ["iMobile.callBackHandler"], callbackjs);
};

iCore.prototype.validateSecureToken = function(value, callbackjs) {
	this.hookRequire("validateSecureToken", [value, "iMobile.callBackHandler"], callbackjs);
};
// Nick added for Green LaiSee end

iClass(iCore);
iFunction.superclass = iCore;
iFunction.synthesizedProperties = ["configuration","viewIndex"];
function iFunction(){
	this.configuration = {
		"settings" : "../../config/settings/global",
		"error" : "../../config/error/nls/error",
		"dps" : "../../config/datePicker/nls/date",
		"auth" : "../../config/auth/nls/auth",
		"handoverToEntity" : "handoverToEntity/handovertoentity"
	};
	Lang.topic("9c9eb9ae133cb5b9",this);
	Lang.topic("a6d38804ceb86f18",this);
	Lang.topic("31bfbda161a1a2ba",this);
	Lang.topic("da3ab016c46c426c",this);
	this.totallRequires = 0;
	this.alreadyDone = 0;
	this.callSuper();
}
iFunction.prototype.setConfiguration = function(configuration){
	this._configuration = Lang.mixin(this._configuration||{},configuration);
}
iFunction.prototype.getConfiguration = function(){
	return this._configuration;
}
iFunction.prototype.getViewIndex = function(){
	return this._viewIndex;
}
iFunction.prototype.setViewIndex = function(index){
	this._viewIndex = index;
	iTransition.disable();
	this.goTo(index);
	iTransition.restore();	
}
/**start MobileUI1.5P2 hot-hot M0001**/
iFunction.prototype.getDomainCallBack= function(domain){
	var self=this;
	self.currentDomain=domain;
	if(domain!=undefined && domain!="")
	{
	  self.configuration.settings.host=self.configuration.settings.protocolString+domain;
  }
	self.runGetLocale();
}
/**end MobileUI1.5P2 hot-hot M0001**/	
iFunction.prototype.getLocale = function(locale){
	var self = this;
	var localemapping=self.configuration.settings.localemapping;
		if(localemapping!=undefined)
		{
			for(var localeKey in localemapping)
	    {
	    	if(locale==localeKey)
	    	{
	    		locale=localemapping[localeKey];
	    		break;
	    	}
	    }
	 }
	require([self.configuration.i18n + "_" + locale, self.configuration.apis,self.configuration.settings.authConfigPath+"auth",self.configuration.auth+"_"+locale,self.configuration.error + "_" + locale],function(i18n,apis,authConfig,auth,err){
		self.apis = apis;
		for(var elementId in authConfig)
    {
      self.apis[elementId]=authConfig[elementId];
    }
		self.configuration.auth = auth;
		//console.log(auth);
		//self.i18n = i18n; //only push i18n data to iData
		iData.add("i18n",i18n);
		
		self.locale = locale;
		self._err = err;
		//init Error
		iMobile.initError(err);
		//function initiate
/**start Mobile1.5 Premier Pack 1**/
		var customerFlagName = self.configuration.settings.customerTypeFlag;
		if(self.configuration.settings.isBrowser){
			self._init();
		}else{
		//self.hookRequire("getter", ["iMobile.callBackHandler"], self.getPremierFlag);
		//self.volatileGetter(customerFlagName,self.getPremierFlag);
		self.volatileGetter(customerFlagName,self.getPremierFlag);
		}
		
		require([self.configuration.dps + "_" + self.locale], function(dps){
			self.configuration.dpsConfig = dps;
			
			
		});
	});
	
	//detect if it's iOS7 iPad, if yes, remove he width=device-width from the viewport 
	var isiOS7Pad = (/ipad/gi).test(navigator.appVersion) && (i_a_v_check("i") >= 7);
	if (isiOS7Pad) {
		var viewports = document.getElementsByName("viewport");
		viewports[0].content = "initial-scale=1.0, maximum-scale=1.0, user-scalable=0";
	}
	//hidden app loading view
	var currentPage=$("#"+self._viewIndex);
	console.log(currentPage.hasClass('prelogon'));
	/* updated for Proposition Background [start] */
	if(currentPage.hasClass('prelogon') && !self.configuration.settings.dummy && !self.configuration.settings.changebgImageAccordingToCustSegment){
		self.logonLoadingFinish();
	}
	/* updated for Proposition Background [end] */
}

// Nick added for GreenLaiSee start
iFunction.prototype.getCustomerInfoKeys = function() {
	var self = this,
	    GLOBAL_CONFIG = self.configuration.settings,
	    customerInfo = GLOBAL_CONFIG.GreenPacket.customerInfo,
	    properties = customerInfo.properties;

	return {
		key: customerInfo.name,
		account: properties.account,
		fullName: properties.fullName,
		company: properties.company,
		location: properties.location,
		secureToken: properties.secureToken,
		sponsorCode: properties.sponsorCode
	};
};

iFunction.prototype.getCustomerInfo = function(callback) {
	var self = this,
	    GLOBAL_CONFIG = self.configuration.settings,
	    customerInfo = GLOBAL_CONFIG.GreenPacket.customerInfo;

	// get customer info from local db
	self.getter(customerInfo.name, function(customerData) {
		customerData = JSON.parse(customerData || "{}");
		callback.call(iFunction.delegate, customerData);
	});
};

iFunction.prototype.setCustomerInfo = function(customerData, callback) {
	var self = this,
	    GLOBAL_CONFIG = self.configuration.settings,
	    customerInfo = GLOBAL_CONFIG.GreenPacket.customerInfo;

	if (typeof customerData === "object") {
		customerData = JSON.stringify(customerData);
	};

	self.setter(customerInfo.name, customerData, function() {
		callback.call(iFunction.delegate);
	});
};
// Nick added for GreenLaiSee end

iFunction.prototype.getPremierFlag = function(data){
		var self = this;
		var customerFlag = data;
		self.preCusLogon = "false";
		console.log("data value is + " + data);
		if(customerFlag=='PRE'){
			$('body').addClass('premier');
			self.preCusLogon = "true";	
			}
		self._init();	
}
/**end Mobile1.5 Premier Pack 1**/
iFunction.prototype._init = function(){
	var hash = location.search, index = 0, self = this, searchView = iFunction.getQueryStringArg('view');
	// get search
	if(typeof searchView !== "undefined" && searchView !== null) {
		index = searchView;
	}
	var pages = $('body > div[role=page]');
	if(this.configuration.settings.rdirect){
		pages.addClass("r-direct");
	}
	pages.addClass('hidden');
	if(this.viewIndex != -1){
		index = this.viewIndex;
	}
	iTransition.disable();
	pages.each(function(i){
		var c = new iViewController(), id = $(this).attr('id');
		c.view = new iView(this);
		self.iViewControllers[id] = c;
		//subscribe the compiler
		Lang.topic("a9eae7d0b1d64f6b/" + id,self);
		Lang.topics["a9eae7d0b1d64f6b/" + id].subscribe(iFunction.compiler);
		if(index == 0 && i == 0){
			index = id;
		}
	});
	this.currentViewController = this.iViewControllers[index];
	//adjust the content area
	// Nick comment out for project Green LaiSees start
	// var cssFlag = 0;
	// cssFlag += navigator.userAgent.match(/OS [4-9]_/) ? 1 : 0; // is IOS 4-9
	// cssFlag += Lang.isOS5 << 1; // is IOS 5+
	// cssFlag += Lang['android4-'] << 2; // is Android 4+
	// Nick comment out for project Green LaiSees end
	var css = '';
	// Nick comment out for project Green LaiSees start
	// if(cssFlag & 1) {
	// 	css += '.ui-list-form3 li select{direction:rtl}';
	// }
	// if(cssFlag & 2 || css & 4) {
	// 	css += 'div[role="content"]{position:relative; -webkit-box-flex:1;box-flex:1; -webkit-overflow-scrolling : touch; -webkit-margin-collapse : separate;}';
	// }
	// if(cssFlag & 2) {
	// 	css += 'body > * {height : 100%;}div[role="content"]{overflow-y : scroll;}div[role="content"] > *{-webkit-transform : translate3d(0,0,0);}';
	// }
	// if(cssFlag & 4) {
	// 	css += '.ui-header{position:fixed !important;margin:0 !important;left:0;right:0;}';
	// 	css += 'div[role=content] #wrapper, div[role=content] #wrapper1, div[role=content] #wrapper2, .ui-header.absolute + div[role=content] .ui-wrapper, .ui-header + *{margin-top: 56px;}';

	// } else {
	// Nick comment out for project Green LaiSees end
		css += 'div[role="page"]{overflow-x:hidden !important}';
	// Nick comment out for project Green LaiSees }
	/*
	if(navigator.userAgent.match(/OS [4-9]_/))
	{
		css += '.ui-list-form3 li select{direction:rtl}';
	}
	if(Lang.isOS5 || Lang['android4-']){
		css += 'body > * {height : 100%;}div[role="content"]{position:relative; -webkit-box-flex:1;box-flex:1;overflow-y : scroll; -webkit-overflow-scrolling : touch; -webkit-margin-collapse : separate;}';
		if(Lang.isAndroid) {
			css += 'div[role=content] #wrapper, div[role=content] #wrapper1, div[role=content] #wrapper2, div[role=content] .ui-wrapper, div[role=content] .ui-float-box{margin-left: 0; margin-right: 0; margin-top: 0;}';
			css += 'div[role=content] #wrapper, div[role=content] #wrapper1, div[role=content] #wrapper2, .ui-header.absolute + div[role=content] .ui-wrapper{margin-top: 56px;}';
			css += 'body > * {height : 100%;}div[role="content"]{overflow-y : visible;}.ui-header{position:fixed !important;margin:0 !important;left:0;right:0;}.ui-header + *{margin-top:56px;}';
		}
		else {
			css += 'div[role="content"] > *{-webkit-transform : translate3d(0,0,0);}';
		}
	}
	if(!Lang['android4-'])
	{
		css += 'div[role="page"]{overflow-x:hidden !important}';
	}
	*/
	if(css) $(document.createElement("style")).attr({type:"text/css",media:"screen"}).html(css).appendTo("head");
	//init error view
	/* customize for green Packet [start] */
	if(!this.errorViewController){
		var errorView  = $('<div id="errorWrapper" role="page" class="page ui-non-bgImg hidden"> ' +
                                '<div role="headbar" class="ui-header nav-back" dcsuri="${nls.wt_err_dcsuri}"> <a role="button" href="javascript:;" class="errorBtnBack"></a> </div>' +
                                '<div class="table-cell">' +
                                   '<div class="inline">' +
                                        '<div class="ui-error-view"></div>' +
                                        '<div class="error-content" role="content"> ' +
                                            '<div id="error-panel" class="ui-error-panel"> <p></p> </div> ' +
                                            '<div class="hidden"> <a role="button" href="javascript:;" class="ui-btn-enter"><span>${nls.continue}</span></a> </div>' +
                                        '</div>' +
                                    '</div>' +
                                '</div>' +
                           '</div>');
		this.errorViewController = new iViewController();
		this.errorViewController.view = new iView(errorView[0]);
		$(document.body).append(errorView);
		this.iViewControllers["errorWrapper"] = this.errorViewController;
		Lang.topic("a9eae7d0b1d64f6b/errorWrapper",self);
		Lang.topics["a9eae7d0b1d64f6b/errorWrapper"].subscribe(iFunction.compiler);		
		errorView = null;
	}
	/* customize for green Packet [end] */
	//init common error view for escaping
	if(!this.commonErroViewController){
	  var message=self.configuration.settings.message[self.locale];
		var commonErrorView = $('<div id="commonError" role="page" class="page ui-non-bgImg hidden"><div role="headbar" class="ui-header nav-back"><a role="button" href="javascript:;" class="nav-btn-back errorBtnBack"></a></div><div class="ui-error-view"></div><div class="error-content" role="content"><div id="error-panel" class="ui-error-panel"><p></p></div></div></div>');
		this.commonErroViewController = new iViewController();
		this.commonErroViewController.view = new iView(commonErrorView[0]);
		$(document.body).append(commonErrorView);
		this.iViewControllers["commonError"] = this.commonErroViewController;
		Lang.topic("a9eae7d0b1d64f6b/commonError",self);
		Lang.topics["a9eae7d0b1d64f6b/commonError"].subscribe(iFunction.compiler);		
		commonErrorView = null;
	}
	//init stepup view
	if(!this.stepUpViewController){
		/* implement for SOTP and mobile 1.5 [start] */
		var auth=self.configuration.auth;
		var stepUpView = $('<div id="stepUp" role="page" class="page hidden"> <div id="stepupCam40-headbar" role="headbar" class="ui-header" dcsuri="'+auth.stepUpWt+'">'
				+' <a role="button" id="stepupCam40_cancel_btn" href="javascript:;" class="ui-back">'+auth.back+'</a> <h1>'+auth.stepup+'</h1>	<a role="button" id="stepupCam40_btn_help" href="javascript:;" class="ui-btn-help">'+auth.help+'</a> </div>'
				+' <div id="reauthCAM40-content" role="content" class="error-content"> <div class="ui-div-container"> <div id="passwordsInfoReauthCAM40" class="ui-div-msg">'
				+' <div class="ui-div-stepUpMsg ui-icon-warn"><div class="ui-div-question">'+ auth.funcNotAvail +'</div><div id="alterTokenInfo">'+auth.genHardOTP+'</div><div class="ui-div-spacing"></div>'+auth.forHelp+'</div></div></div>'
				+' <div class="ui-div-inputPanel"><label id="inputNote">'+auth.enterSecurityCode+'</label><div class="inputDiv"><input aria-label="'+auth.enterSecurityCode+'" id="stepup_OtpCredential"  maxlength="6"  pattern="[0-9]*" type="password" /></div><a role="button" aria-disabled="true" id="stepupCam40_confirm" href="javascript:;" class="ui-btn-enter disabled login"><span>'+auth.continue_btn+'</span></a></div>'
				+'</div> </div>');
			 
		this.stepUpViewController = new iViewController();
		this.stepUpViewController.view = new iView(stepUpView[0]);
		$(document.body).append(stepUpView);
		this.iViewControllers["stepUp"] = this.stepUpViewController;
		Lang.topic("a9eae7d0b1d64f6b/stepUp",self);
		Lang.topics["a9eae7d0b1d64f6b/stepUp"].subscribe(iFunction.compiler);		
		stepUpView = null;
		/*var auth=self.configuration.auth;
    var stepUpView = $('<div id="stepUp" role="page" class="page hidden"> <div id="stepupCam40-headbar" role="headbar" class="ui-header" dcsuri="'+auth.stepUpWt+'">'
			+' <a id="stepupCam40_cancel_btn" href="javascript:;" class="ui-btn-next ui-android-back">'+auth.cancel+'</a> <h1>'+auth.stepup+'</h1>	<a id="stepupCam40_btn_help" href="javascript:;" class="ui-btn-help">'+auth.help+'</a> </div>'
			+' <div id="reauthCAM40-content" role="content" class="ui-content"> <div id="passwordsInfoReauthCAM40" class="ui-pwd-stepup"><h4>'+auth.stepupInfo+'</h4></div>	'
			+' <ul class="ui-ul-input">  <li> <input id="stepup_OtpCredential"  maxlength="6"  pattern="[0-9]*" type="password" placeholder="'+auth.securityCodeDesc+'"/> </li> </ul>'
			+' <a id="stepupCam40_confirm" href="javascript:;" class="ui-btn-enter disabled"><span>'+auth.continue_btn+'</span></a> </div> </div>');
			 
		this.stepUpViewController = new iViewController();
		this.stepUpViewController.view = new iView(stepUpView[0]);
		$(document.body).append(stepUpView);
		this.iViewControllers["stepUp"] = this.stepUpViewController;
		Lang.topic("a9eae7d0b1d64f6b/stepUp",self);
		Lang.topics["a9eae7d0b1d64f6b/stepUp"].subscribe(iFunction.compiler);		
		stepUpView = null;*/
		/* implement for SOTP and mobile 1.5 [end] */
	}
	
	//init reAuth
	if(!this.reAuthViewController){
		var auth=self.configuration.auth;
		var reAuthView = $('<div id="reAuth" role="page" class="page actionsheet hidden"><div id="reauthCam3040-headbar" role="headbar" class="ui-header withoutBg" dcsuri="'+auth.reAuthWt+'">'
	               +' <a role="button" id="reauthCam3040_cancel_btn" href="javascript:;" class="ui-btn-icon withoutBg ui-android-back">'+auth.cancel+'</a>'
	               +' <h1 id="reauthCam30H1"  class="longwords">'+auth.reauCam30+'</h1> <h1 id="reauthCam40H1">'+auth.reauCam40+'</h1></div>'
	               +' <a role="button" id="reauthCam40_btn_help" href="javascript:;" class="ui-btn-icon withoutBg ui-left ui-android-help">'+auth.help+'</a>'
	               +' <div id="reauthCam30-content" role="content" class="ui-content"><div id="reauth_passwordsInfoCAM30" class="ui-pwd-info"></div>'
	               +' <div id="passwordsInfoCAM40" class="ui-pwd-info"><h4>'+auth.cam40Info+'</h4></div>'
	               +' <ul class="ui-ul-input shadow-rgba">'
	               +' <li><div id="reauth_secondPassword" class="dualPwdLine hidden"></div><input id="idv_OtpCredential"  pattern="[0-9]*" maxlength="6" type="password" placeholder="'+auth.securityCodeDesc+'"/></li>'
	               +' </ul> <a role="button" aria-disabled="true" id="reauthCam30_confirm" href="javascript:;" class="ui-btn-enter disabled"><span>'+auth.continue_btn+'</span></a>'
	               +' <a role="button" aria-disabled="true" id="reauthCam40_confirm" href="javascript:;" class="ui-btn-enter disabled hidden"><span>'+auth.continue_btn+'</span></a>	</div></div>');
		this.reAuthViewController = new iViewController();
		this.reAuthViewController.view = new iView(reAuthView[0]);
		$(document.body).append(reAuthView);
		this.iViewControllers["reAuth"] = this.reAuthViewController;
		Lang.topic("a9eae7d0b1d64f6b/reAuth",self);
		Lang.topics["a9eae7d0b1d64f6b/reAuth"].subscribe(iFunction.compiler);		
		reAuthView = null;
	}
	
	/* implement for SOTP [start] */
	//init insuffCredential
	//need uiSOTP.css to render the layout
	if(!this.insuffCredViewController && self.configuration.settings.isHTMLSupportSOTP){
		var auth=self.configuration.auth;
		var insuffCredView = $('<div id="insuffCredential" role="page" class="page hidden disableAndroidBack">'
				+'<div id="insuffCredential-headbar" role="headbar" class="ui-header" dcsuri="'+ auth.wt_insuffCredential +'"><a role="button" id="insuffCredential_btn_back" href="javascript:;" class="ui-back">'+ auth.back +'</a><h1>'+ auth.funcUnavail +'</h1><a role="button" id="insuffCredential_btn_help" href="javascript:;" class="ui-btn-help">'+ auth.help +'</a></div>'
				+'<div id="insuffCredential-content" role="content" class="ui-content"><div class="ui-div-msg"><div class="ui-div-question">'+ auth.funcNotAvail +'</div>'+ auth.needToken +'<div class="ui-div-spacing"></div>	<div class="ui-div-question">'+ auth.activateSOTP +'</div>'+ auth.sotpIntroduce +'<div class="ui-div-spacing"></div>'+ auth.callIfNotSuitable +'</div>'
				+'<div class="ui-pwd-info"></div><a role="button" id="insuffCredential_btn_activate" href="javascript:;" class="ui-btn-enter ui-btnMargin"><span>'+ auth.activateNow +'</span></a><a role="button" id="insuffCredential_btn_callService" href="javascript:;" class="ui-btn-enter ui-btnMargin ui-light"><span>'+ auth.callService +'</span></a></div></div>');
		this.insuffCredViewController = new iViewController();
		this.insuffCredViewController.view = new iView(insuffCredView[0]);
		$(document.body).append(insuffCredView);
		this.iViewControllers["insuffCredential"] = this.insuffCredViewController;
		Lang.topic("a9eae7d0b1d64f6b/insuffCredential",self);
		Lang.topics["a9eae7d0b1d64f6b/insuffCredential"].subscribe(iFunction.compiler);		
		insuffCredView = null;
	}
	/* implement for SOTP [end] */
	
	//get the dim button each view
	Lang.topics['31bfbda161a1a2ba'].subscribe(function(page){
		this.__currentDimButton  = $('a.dim',page);
		//this.totallRequires = $("input[require=true],select[require=true],textarear[require=true],a>div[require=true]",page).size();
		this.totallRequires =0;
		this.alreadyDone = 0;
	});
	//fields building begin
	if(self['reconstruction'] && $.isFunction(self['reconstruction'])){
		self['reconstruction'].call(self);
	}
	//fields building end
	//below will be revised soon
	this.keyframe = "fade";
	this.currentViewController = this.setTransition(this.currentViewController);
	if(!this.controller){
		this.controller = new iNavigationController(this.currentViewController);
	}	
	
	initWebtrends(self.configuration.settings.wtSettings);
	var dcsuri=$(this.currentViewController.view.layer).find("div[role=headbar]").attr('dcsuri');
	if(dcsuri!=undefined)
	{
	  runTrackWebtrends(self.configuration.settings.wtSettings,self.locale,dcsuri);
	}
	this._history.unshift(this.currentViewController.view.layer.id);
	iTransition.restore();

	this.pageStatusIsChanged(this.currentViewController.view.layer);
}
/**
 * Do not override this function
 * This is quite important
 */
iFunction.prototype._analyse = function(data,adapt,execute){
	
	var rs = {valid : false, errorCode : false, errorMsg : "", data : data},self = this;
	if(!data){
		rs.errorCode = "jsonErr";
		rs.data = {};
		rs.errorMsg = self._err[rs.errorCode];
		execute(rs);
		return;
	}
	if(typeof data === "string"){
		try{
			data = $.parseJSON(data);
			rs.data = data;
			//rs.valid = true;
		}catch(err){
			var aStart = data.indexOf('<json>'), aEnd = data.indexOf('</json>');
			if(aStart > -1 && aEnd > -1){
				var aspectJSON = data.substring(aStart + 6, aEnd);
				try{
					data = $.parseJSON(aspectJSON);
					rs.data = data;
					//rs.valid = true;					
				}catch(e){
					rs.errorCode = "noService";
					rs.errorMsg = self._err[rs.errorCode];
					execute(rs); return;
				}
			}else{
				rs.errorCode = "jsonErr"; rs.errorMsg = self._err[rs.errorCode];  execute(rs); return;
			}
		}
	}
	
	if(typeof rs.data === "object"){
		if(rs.data==null)
		{
			rs.errorCode = "jsonErr"; rs.errorMsg = self._err[rs.errorCode];  execute(rs); return;
		}
		if(!rs.data.hasOwnProperty('header')){
			rs.errorCode = 'headerErr';
		}else if(!rs.data.header.hasOwnProperty('statusCode')){
			rs.errorCode = 'statusCodeErr';
		}
		if(rs.errorCode !== false){
			rs.errorMsg = self._err[rs.errorCode];
			execute(rs);
			return;
		}
		
		//json schema
		require([adapt],function(adapt){
			if(data.header.statusCode == '0000'){
				var schema = iMobile.adaptRegister(data,{"type":"object","properties" : adapt});
				if(schema.valid && schema.errors.length == 0){
					rs.valid = true;
				}else{
					rs.errorCode = 'adaptErr';
					for(var i = 0, l = schema.errors.length; i < l; i++){
						
						if(self.configuration.settings.isEnableJsonLog){
							rs.errorMsg += schema.errors[i].property + ":" + schema.errors[i].message + "<br/>";
						}else{
							//Mass error message.
							rs.errorMsg += schema.errors[i].message + "<br/>";
						}
						
					}				
				}
			} else if (data.header.statusCode == 'W000') {
				// Add handling for multiple request. W000: transaction is pending for another request while current response is valid.
				// Skip JSON schema validation for 'W000' status as no further extraction of this response should be performed.
				rs.valid = ture;
			}
			// Add handling for multiple request. W000: transaction is pending for another request while current response is valid.
			if(data.header.statusCode != '0000' && data.header.statusCode != 'W000'){
					rs.valid = false;
					rs.errorCode = data.header.statusCode;
					rs.errorMsg = data.header.errorMsg;
			}
			execute(rs);				
		});		
	}else{
		rs.errorCode = "jsonErr";
		rs.data = {};
		rs.errorMsg = self._err[rs.errorCode];  
		execute(rs); 
		return;		
	}		
}
iFunction.prototype._jsonpAnalyse = function(data,adapt,execute){
	var rs = {valid : false, errorCode : false, errorMsg : "", data : data},self = this;
	if(!data){
		rs.errorCode = "jsonErr";
		rs.data = {};
		rs.errorMsg = self._err[rs.errorCode];
		execute(rs);
		return;
	}
	if(typeof data === "string"){
		  data=data.replace(/(^\s*)|(\s*$)/g, ""); 
      var bStart = data.indexOf('('), bEnd = data.lastIndexOf(')');
      data=data.substring(bStart+1, bEnd);
		 	try{
				data = $.parseJSON(data);
				rs.data = data;
				rs.valid = true;
				execute(rs); 
		  }catch(err){
		    rs.data = {};
		    execute(rs); 
	    }
	    return;
  }
	if(typeof rs.data === "object"){
		rs.data = data;
		rs.valid = true;
		execute(rs); 
		return;
	}
}
iFunction.prototype._jsonpMessageHandler = function(name,handler,rs){
	
	handler.success.apply(self,[rs]);
	return;
}
iFunction.prototype._messageHandler = function(name,handler,rs){
	
	//update the data model begin
	iData.add(name,rs.data);
	var tempHandler=handler;
	
	//end
	var self = this;
	if(rs.valid){
		$(".warningWrapper").addClass("hidden");
		handler.success.apply(self,[rs]);
		return;
	}
	if(handler.error && $.isFunction(handler.error)){
		var rsData=rs.data;
		if(rsData!=undefined && rsData!='' && rsData.hasOwnProperty('header'))
		{
		  handler.error.apply(self,[rs]);
	  }
	}
	var errorConfig = this.apis[name]['err'], statusCode = rs.errorCode, error = rs.errorMsg, errorCode = [], errorMsg = [], target = "errorWrapper", handler=null, err,warningWrapper=null,animation=null,isShowCancel=null;
	/*dcd multiple logon fix*/
	var dcsuri = $(self.currentViewController.view.layer).find("div[role=headbar]").attr('dcsuri');
	/*dcd multiple logon fix */
	if($.isArray(error)){
		errorCode[0] = statusCode;
		errorMsg[0] = self._err[statusCode]||"";
		/* customize for green Packet [start] */
		if(errorMsg[0].indexOf(self._err['delimiter']) > 0){
			// divide the desc string into title and msg
			var errMsgArr = errorMsg[0].split(self._err['delimiter']);
			console.log(errMsgArr);
			if(errMsgArr[0] != null && errMsgArr[0]!=''){
				errorMsg[0] = '<span style="font-size:20px; color:#8bc53f; padding-bottom:3px; display:block;">' + errMsgArr[0] + '</span>' + errMsgArr[1];
			}
		}
		/* customize for green Packet [end] */
		for(var i = 0, l = error.length; i<l; i++){
			errorCode[i] = error[i].code;
			/* implement for SOTP and mobile 1.5 [start] */
			if(i==0 && error[i].desc.indexOf(self._err['delimiter']) > 0){
				// divide the desc string into title and msg
				var errMsgArr = error[i].desc.split(self._err['delimiter']);
				if(errMsgArr[0] != null && errMsgArr[0]!=''){
					error[i].desc = '<span style="font-weight:bold; color:#8bc53f; padding-bottom:3px;display:block;">' + errMsgArr[0] + '</span>' + errMsgArr[1];
				}
			}
			/* implement for SOTP and mobile 1.5 [end] */
			errorMsg[i] = error[i].desc||errorMsg[i]||self._err[statusCode]||"";
		}
	}else if(Lang.isString(error)){
		//no error code, use statusCode
		errorCode[0] = statusCode;
		/* implement for SOTP and mobile 1.5 [start] */
		if(error.indexOf(self._err['delimiter']) > 0){
			// divide the desc string into title and msg
			var errMsgArr = error.split(self._err['delimiter']);
			if(errMsgArr[0] != null && errMsgArr[0]!=''){
				error = '<span style="font-size:20px; color:#8bc53f; padding-bottom:3px; display:block;">' + errMsgArr[0] + '</span>' + errMsgArr[1];
			}
		}
		/* implement for SOTP and mobile 1.5 [end] */
		errorMsg[0] = error;
	}else if(error==undefined){
		 errorCode[0] = statusCode;
		/* customize for green Packet [start] */
		error = self._err[statusCode]||"";
		if(error.indexOf(self._err['delimiter']) > 0){
			// divide the desc string into title and msg
			var errMsgArr = error.split(self._err['delimiter']);
			if(errMsgArr[0] != null && errMsgArr[0]!=''){
				error = '<span style="font-size:20px; color:#8bc53f; padding-bottom:3px; display:block;">' + errMsgArr[0] + '</span>' + errMsgArr[1];
			}
		}
		 errorMsg[0] = error;
		/* customize for green Packet [end] */
	}
	
	
	if(errorCode.length > 1){
		errorCode =  errorCode[0];
		errorMsg = errorMsg.join("<br/>");
	}else if(errorCode.length == 1){
		errorCode = errorCode[0];
		errorMsg = errorMsg[0];
	}
	if(errorCode!=undefined&&errorCode!=""){
		if(errorCode !== statusCode){
			for(err in errorConfig){
				if(err.indexOf(statusCode) > -1){
					target = errorConfig[err].target || target;
				  handler = errorConfig[err].handler;
				  warningWrapper= errorConfig[err].warningWrapper;	
				  animation=errorConfig[err].animation;	
				  isShowCancel=errorConfig[err].isShowCancel;	
					for(var e in errorConfig[err]){
						if(e.indexOf(errorCode) > -1){
							target = errorConfig[err][e].target || target;
							handler = errorConfig[err][e].handler|| handler;
							warningWrapper= errorConfig[err][e].warningWrapper|| warningWrapper;
							animation= errorConfig[err][e].animation|| animation;
							var tempIsShowCancel= errorConfig[err][e].isShowCancel;
								if(tempIsShowCancel!=undefined){
								isShowCancel=tempIsShowCancel;
							}
							isShowCancel= errorConfig[err][e].isShowCancel|| isShowCancel;
							matchErrCode=true;
							break;
						}
					}
					break;
				}
			}		
		}else{
			for(err in errorConfig){
				if(err.indexOf(errorCode) > -1){
					target = errorConfig[err].target || target;
					handler = errorConfig[err].handler;
					warningWrapper= errorConfig[err].warningWrapper;
					animation= errorConfig[err].animation;
					isShowCancel= errorConfig[err].isShowCancel;
					break;
				}
			}
		}
	}
	//Multiple logon error handle
	if(statusCode=="C006" || statusCode=="C012")
	{
	 errorMsg=self._err[statusCode];
	}
	if(statusCode=="C001"){
		if(self.configuration.settings.securityType === "SaaS"){
			var lastReqForTimeout = iData.get("lastReq"), url = (lastReqForTimeout.url || (self.configuration.settings.host + self.apis[lastReqForTimeout.name].url));
		  	var domain = url.split("/")[0]+ "//"+url.split("/")[2];
		  	
		    if(!self.saasTimeout){   	//load timeout.js
		    	require(["SaaS/timeout"], function(SaaSTimeout){
		    		self.saasTimeout = new SaaSTimeout(self);  
		  			 //call the api from timeout to check, pass the last request for handling
		    		self.saasTimeout.checkTimeout(domain, self.locale, function(){
		    			self.request(lastReqForTimeout);   //re-send previous request
		    		});
		  		});
		    }else{
		  		//call the api from timeout to check, pass the last request for handling
		  		self.saasTimeout.checkTimeout(domain, self.locale, function(){
		  			self.request(lastReqForTimeout);   //re-send previous request
		  		});
		  	}
		  	return;
		}else if(self.configuration.settings.securityType === "Legacy"){
			self._isTimeout=true;
		}	   
  }
	this._multipleLogonError = false;
	/*dcd multiple logon fix*/
	if((errorCode!=undefined && errorCode!='' && ((errorCode.indexOf('0014')!=-1 && statusCode=="C000")|| (statusCode=="C006") )) || (errorMsg.indexOf("8010")!= -1 && dcsuri.indexOf("dcd") != -1 && statusCode == "E000"))
	{
		this._multipleLogonError = true;
		//fix multiple logon error - start - 14Oct2013
		self.request({name : 'timeoutLogoff',adaptorPath:self.configuration.settings.authConfigPath, method : 'post', data : self.timeoutLogoffData});
		//fix multiple logon error - end - 14Oct2013
	}
	this._commonError = false;
	this._backToApp=false;
	
	if(self.configuration.settings.error_back_mapping[statusCode] && !handler && target != "goToSuccess" && target != "handleByPage" && target != "warning"){
		target = "commonError";
	}	
	//check out if it is a common error or not
	if(target === 'commonError'){
		//hide back button in errorView
		/*dcd multiple logon fix*/
		if(self.configuration.settings.error_back_mapping[statusCode]=='backToApp' ||(errorMsg.indexOf("8010")!= -1 && dcsuri.indexOf("dcd") != -1 && statusCode == "E000"))
		{
			this._backToApp=true;
			target = 'errorWrapper';
		  $("a.errorBtnOK",this.errorViewController.view.layer).removeClass('hidden');
		  $("a.errorBtnCancel",this.errorViewController.view.layer).addClass('hidden');
		  $("a.errorBtnBack",this.errorViewController.view.layer).addClass('hidden');
		}else{
			/* customize for green Packet [start] */
			$('div.ui-error-panel>p',self.commonErroViewController.view.layer).html(errorMsg||self._err['noService']);
			/* customize for green Packet [end] */
		}
		this._commonError = true;
	}
	else{
		if(!handler || !Lang.isFunction(self[handler])){
			// Nick removed for GreenLaiSee start
			// handler = self.configuration.settings.error_back_mapping[statusCode]||"goBack";
			// Nick removed for GreenLaiSee end
			// Nick added for GreenLaiSee start
			handler = self.configuration.settings.error_back_mapping[statusCode];
			// Nick added for GreenLaiSee end
		}
		this._handler = handler;
		if(isShowCancel==true){
			$("a.errorBtnCancel",this.errorViewController.view.layer).removeClass('hidden');
			$("a.errorBtnBack",this.errorViewController.view.layer).addClass('hidden');
			$("a.errorBtnOK",this.errorViewController.view.layer).addClass('hidden');
		}else{
		  $("a.errorBtnOK",this.errorViewController.view.layer).addClass('hidden');
		  $("a.errorBtnCancel",this.errorViewController.view.layer).addClass('hidden');
		  $("a.errorBtnBack",this.errorViewController.view.layer).removeClass('hidden');
		}
	}
	//if errorMsg is null then show noService msg
	/*dcd multiple logon fix*/
	if(errorMsg.indexOf("8010")!= -1 && dcsuri.indexOf("dcd") != -1 && statusCode == "E000"){
		errorMsg = self._err["C006"];
	}
	/*dcd multiple logon fix*/
	/* customize for green Packet [start] */
	$('div.ui-error-panel>p',self.errorViewController.view.layer).html(errorMsg||self._err['noService']);
	/* customize for green Packet [end] */
	if(target != undefined && target == "goToSuccess")
	{
		if(warningWrapper!= undefined)
		{
			$("#"+warningWrapper).addClass("error-content").find("div:first").removeClass("hidden").html(errorMsg);
			$("#"+warningWrapper).removeClass("hidden");
	  }
		tempHandler.success.apply(self,[rs]);
		return;
	}
	//step up
	if(statusCode=="C003")
	{
		if(self.configuration.settings.securityType == "SaaS"){
			var lastReqForStepup = iData.get("lastReq"), url = (lastReqForStepup.url || (self.apis[lastReqForStepup.name].url));
			//saas mock for testing.
			console.log("SaaS:last reqeust url is - "+url);
		  	var domain = url.split("/")[0]+ "//"+url.split("/")[2];
		  	
		    if(!self.saasStepup){   	//load stepup.js
		    	require(["SaaS/stepup"], function(SaaSStepup){
		    		self.saasStepup = new SaaSStepup(self);  
		  			 //call the api from stepup to check, pass the last request for handling
		    		self.saasStepup.requestStepup(domain, self.locale, function(){
					    //add for saas mock testing , need to remove later
		    			self.request(lastReqForStepup);   //re-send previous request
		    		});
		  		});
		    }else{
		  		//call the api from stepup to check, pass the last request for handling
		  		self.saasStepup.requestStepup(domain, self.locale, function(){
				  //add for saas mock testing , need to remove later
		    			self.request(lastReqForStepup);   //re-send previous request
		  		});
		  	}
		  	return;
		}else if(self.configuration.settings.securityType == "Legacy"){
			iData.add("reqBeforeStepUp",iData.get('lastReq'));
			self.goTo("stepUp","fade");
			return;
		}
	}
	else if(statusCode=="C002" )
	{
		 self.request({name : 'reAuthCheck',adaptorPath:self.configuration.settings.authConfigPath, method : 'post', data : self.reauthCheckSubmitData,callback : self.reauthCheckCallBack });
     return;
	}else if(statusCode=="C012" && self.configuration.settings.isHTMLSupportSOTP && self._isAppSupportSOTP == 'true'){/* implement for SOTP [start] */
		self.goTo("insuffCredential","fade");
		return;
		/* implement for SOTP [end] */
	}
	else if(target != "warning" && target != "handleByPage")
	{
		 if(this._commonError==true)
		 {
		 	// Nick removed for GreenLaiSee start
		 	// self.goTo(target,"slideup");
		 	// Nick removed for GreenLaiSee end
		 	// Nick added for GreenLaiSee start
		 	self.goTo(target);
		 	// Nick added for GreenLaiSee end
		 }
		 else
		 {
		 	 if(animation!=undefined && animation!=null && animation!='')
		 	 {
		     self.goTo(target,animation);
		   }
		   else
		   	 self.goTo(target);
		 }
	}
	
}

/* customize for green Packet [start] */
iFunction.prototype.errorWrapperHasParsed = function(){
	var self = this;
	$("a.errorBtnBack",this.errorViewController.view.layer).click(function(){
		if(self[self._handler] && $.isFunction(self[self._handler]) && self._handler !== 'goBack'){
			self[self._handler].call(self);
		// Nick added start
		} else if (self._handler === "goBack") {
			self.goBack();
		// Nick added end
		}else{
			var toPage = 'file:///web/postlogon/menu/menu.html';
			self.goBack(toPage, true);
		}
	});		
}
/* customize for green Packet [end] */
iFunction.prototype.commonErrorHasParsed = function(){
	var self = this;
	// Nick removed for GreenLaiSee start
	// $("a.ui-btn-menu",self.commonErroViewController.view.layer).fastClick(function(){
	// 	self.toggleMenu();
	// });
	// Nick removed for GreenLaiSee end
	// Nick added for GreenLaiSee start
	$("a.errorBtnBack", this.commonErroViewController.view.layer).click(function() {
		if(self[self._handler] && $.isFunction(self[self._handler])){
			self[self._handler].call(self);
		}else{
			var toPage = 'file:///web/postlogon/menu/menu.html';
			self.goBack(toPage, true);
		}
	});
	// Nick added for GreenLaiSee end
}
/**
 *Do not override this function
 */
iFunction.compiler = function(data, page){
	var self = this.delegate, parseHandler = page.id + "HasParsed";
	iFunction.showMenuAfterFirstLogon().done(function() {
		//rebuild the data model
		if(self['buildModel'] && $.isFunction(self['buildModel'])){
			self['buildModel'].call(self);
		}	
		//publish the dim handler
		Lang.topics["a6d38804ceb86f18"].publish($("input[require=true],select[require=true],textarear[require=true],a>div[require=true]",page));
		//publish the parse handler
		if(self[parseHandler] && $.isFunction(self[parseHandler])){
			self[parseHandler].apply(self,[page]);
		}
	});
	
}
iFunction.showMenuAfterFirstLogon = function(){
	var deferred = $.Deferred();
	if(typeof iFunction.isLogonned === 'undefined') {
		if(iFunction.getQueryStringArg('showMenu') === "true") {
			iFunction.delegate.toggleMenu();
			setTimeout(deferred.resolve, 100);
		} else {
			deferred.resolve();
		}
		
		iFunction.isLogonned = true;
	} else {
		deferred.resolve();
	}
	return deferred.promise();
}
/**
 * Change menu status
 */
iFunction.menuStatusEventJS = function(isMenuExpanded, appName){
	isMenuExpanded = (typeof isMenuExpanded === 'string') ? Boolean($.parseJSON(isMenuExpanded)) : Boolean(isMenuExpanded);
	if(isMenuExpanded) {
		$('body').addClass('menu-expanded');
		if(Lang.isAndroid) {
			$('.ui-header h1:not(:has(span.title-function))').wrapInner('<span class="title-function" />').prepend('<span class="title-apps">' + appName + '</span>');
		}
	} else {
		$('body').removeClass('menu-expanded');
	}
}
/**
 * Get parsed window.location.search
 */
iFunction.getQueryStringArgs = function(urlObject){
	// set default url = location
	if(typeof urlObject === 'undefined') urlObject = location;
	// return saved result (only for urlObject === location)
	if(urlObject === location && typeof iFunction.queryStringArgs !== 'undefined') return iFunction.queryStringArgs;
	var search = urlObject.search, obj = {};
	// return if no window.search
	if($.trim(search).length == 0) {
		if(urlObject == location) iFunction.queryStringArgs = obj;
		return obj;
	}
	// parse search
	search = search.slice(1).split('&');
	var i = 0, pair;
	for(var i=0; i <search.length; i++){
		pair = search[i].split('=');
		obj[decodeURIComponent(pair[0])] = (typeof pair[1] !== 'undefined') ? decodeURIComponent(pair[1]) : null;
	}
	// return result
	if(urlObject == location) iFunction.queryStringArgs = obj;
	return obj;
}
iFunction.getQueryStringArg = function(key, url){
	return iFunction.getQueryStringArgs(url)[key];
}
iFunction.queryStringArgsToString = function(searchObject){
	if(searchObject == {}) return '';
	var outputObject = [];
	$.each(searchObject, function(key, value) {
		if(typeof value === 'undefined') return true;
		if(value === null) outputObject.push(encodeURIComponent(key));
		else outputObject.push(encodeURIComponent(key) + '=' + encodeURIComponent(value));
	});
	return '?' + outputObject.join('&');
}
/**
 * Add ui=a when Android
 */
iFunction.setQueryForUiIfNeeded = function(url){
	/*
	var anchorDom, anchorQueryStringArgs;
	if(Lang.isAndroid){
		// borrow a tag to parse url
		anchorDom = document.createElement('a');
		anchorDom.href = url;
		anchorQueryStringArgs = iFunction.getQueryStringArgs(anchorDom);
		anchorQueryStringArgs.ui = 'a';
		anchorDom.search = iFunction.queryStringArgsToString(anchorQueryStringArgs);
		return anchorDom.href;
	}
	*/
	return url;
}
/**
 *	dim button handler
 */
iFunction.dimOrNotBaseOnRequireFields = function(requires){
	var delegate = this.delegate;
	if(!requires || !delegate.__currentDimButton) return;
	delegate.totallRequires += requires.length;
	function watch(obj,btn){
		if(($(obj).val()!=''||$(obj).hasClass('ui-highLight')) && !obj.valued){
			obj.valued = true;
			delegate.alreadyDone++;
		}else if((obj.nodeName == "INPUT"||obj.nodeName == "SELECT" || obj.nodeName == "TEXTAREA") && $(obj).val()==''){
			if(obj.valued){
				obj.valued = false;
				delegate.alreadyDone--;				
			}
		}		
		if(delegate.totallRequires == delegate.alreadyDone){
			btn.removeClass('disabled');
			btn.attr("aria-disabled","false");
		}else{
			btn.addClass('disabled');
			btn.attr("aria-disabled","true");
		}
	}
	requires.each(function(){
		if(this.nodeName == "INPUT" || this.nodeName == "TEXTAREA"){
			$(this).on("keyup", function(){
				if($(this).attr("require") == "true"){
					watch(this,delegate.__currentDimButton);
				}
			});
		}
		if(this.nodeName == "SELECT"){
			$(this).on("change",function(){
				if($(this).attr("require") == "true"){
					watch(this,delegate.__currentDimButton);
				}
				
			});
		}
		if(this.nodeName == "DIV"){
			if($(this).attr("require") == "true"){
				watch(this,delegate.__currentDimButton);
			}
		}
	});
}
iFunction.prototype.handoverToEntity = function(postLogonData, scope, context){
	var self = context||this;
	require([self.configuration.handoverToEntity, "handover/handoverToEntity"], function(handoverToEntity, handover){
		self.apis = Lang.mixin(self.apis, handoverToEntity||{});
		handover.apply(self, [postLogonData,scope]);
	});
};
/**
 * iScroll default options
 */
iFunction.iScrollMergeDefaultOptions = function(options) {
	var defaultOptions = {
		isNotSupportAndroid3D: !(Lang.isOS5 || Lang['android4-'])
	}
	
	return $.extend(defaultOptions, options);
};
iClass(iFunction);
//webtrends
window.iWebtrend = function(){
	//implement webtrend here
	var self = iFunction.delegate;
	var dcsuri=$(self.currentViewController.view.layer).find("div[role=headbar]").attr('dcsuri');
	if(self.fromDcsUri!=undefined && dcsuri!=undefined)
	{
		  runTrackWebtrends(self.configuration.settings.wtSettings,self.locale,dcsuri);
	}
};

$.fn.makeToBeRequired = function(delegate){	
	if($(this).attr("require")== "true")
	{
		return;
	} 
	$(this).attr("require","true");
	delegate.__currentDimButton.addClass('disabled');
	delegate.__currentDimButton.attr("aria-disabled","true");
	Lang.topics["a6d38804ceb86f18"].publish($(this));
};
$.fn.removeRequired = function(delegate){
	if($(this).attr("require")== "true"){
		$(this).removeAttr("require");
		if(delegate.alreadyDone === delegate.totallRequires){
			delegate.alreadyDone--;
		}
		delegate.totallRequires--;		
	}
};
//do not remove
$(function(){
	iFunction.delegate = Lang.topics['jq'].get()();
});

function initWebtrends(wtSettings){
	var dcs = new Webtrends.dcs();
	  dcs.init( {
	          dcsid: wtSettings.dcs.dcsid,
	          domain:wtSettings.dcs.domain,
	          disablecookie:wtSettings.dcs.disablecookie
	  });
}

function runTrackWebtrends(wtSettings,locale,dcsuri){
	/**webtrend enhancement for android tablet - start**/
	var self = iFunction.delegate;	
	if (self.devType == "T") {
		dcsuri = dcsuri.replace(/\/mobile\//, "\/tablet\/");
	}
	console.log("dcsuri: " + dcsuri);
	/**webtrend enhancement for android tablet - end**/
	var args={"DCS.dcsuri" : dcsuri,"DCS.language" : locale};
	var wtArgs=wtSettings.args;
	if(wtArgs!=undefined && wtArgs!=null)
	{
  	for(var elementId in wtArgs)
    {
      args['DCS.'+elementId]=wtArgs[elementId];
    }
	}
	Webtrends.multiTrack({
      args: args
  });
}


function hookAPIFailCall(str){
	var objJSON = $.parseJSON(str);
	if(objJSON.header.statusCode === 'P003'){
		//caused by mismatch between APP and HTML for SOTP
		iMobile.callBackHandler('{"DataOutput":{"statusCode":"XXXX"}}');
	}
}
// IBTRM added start
var SessionCheckSvc = (function(){
	var self = this,
		delegate = iFunction.delegate,
		SHOW_SESSIONCHECKING_FUNC_NAME = "SessionCheckSvc.showSessionCheckingPage",
		TIMEOUT_REAUTH_PAGE_PATH = "file:///web/banking/sessionChecking/sessionChecking.html";

	return {
		"registerBackToForeEvent": function(callbackjs){
			var args=[SHOW_SESSIONCHECKING_FUNC_NAME];
			
			if(callbackjs){
				args.push(callbackjs);
			}
			iMobile.app["registerBackToForeEvent"].apply(self, args);
		},

		"unregisterBackToForeEvent": function(callbackjs){
			var args=[];

			if(callbackjs){
				args.push(callbackjs);
			}
			iMobile.app["unregisterBackToForeEvent"].apply(self, args);
		},

		"showSessionCheckingPage": function(){
			var args = [TIMEOUT_REAUTH_PAGE_PATH];
			
			iMobile.app["showOverlay"].apply(self, args);
		},

		"hideSessionCheckingPage": function(){
			iMobile.app["removeOverlay"].apply(self, []);
		}
	};
})();
// IBTRM added end
